Question

Im essayant d'utiliser le cadre JSON.NET dans un formulaire de fenêtres pour lire des informations à partir d'une chaîne JSON. Mais im luttent pour obtenir les dictionnaires de la « taxonomies-> sujets » ensemble et les « clusters »

{
    "keywords": {
        "anyString": [

        ],
        "allString": {
            "a5349f533e3aa3ccbc27de2638da38d6": "olympics"
        },
        "exactString": [

        ],
        "notString": [

        ],
        "highlightString": [

        ]
    },
    "dates": {
        "startDate": "15-01-2008",
        "endDate": "15-09-2009",
        "useDates": true
    },
    "clusters": {
        "permission": {
            "1": "private\/n"
        }
    },
    "taxonomies": {
        "Topics": {
            "2488": "Olympics 2012 (not participation)",
            "8876": "Olympics and culture"
        },
        "Keywords": {
            "8848": "Engineering in the Olympics"
        }
    },
    "sort": {
        "sortId": 1,
        "sortType": 2,
        "sort": "datetime",
        "sortOrder": "descending"
    }
}

Avec le code ci-dessous j'ai pu lire la partie des informations.

JObject searchCriteria = JObject.Parse(contentSearchCriteria);  
//search criteria   
IEnumerable<string> allString = searchCriteria["keywords"]["allString"].Children().Values<string>();
IEnumerable<string> anyString = searchCriteria["keywords"]["anyString"].Children().Values<string>();
IEnumerable<string> notString = searchCriteria["keywords"]["notString"].Children().Values<string>();
IEnumerable<string> exactString = searchCriteria["keywords"]["exactString"].Children().Values<string>();
IEnumerable<string> highlightString = searchCriteria["keywords"]["highlightString"].Children().Values<string>();
//dates
string startDate = (string)searchCriteria["dates"]["startDate"];
string endDate = (string)searchCriteria["dates"]["endDate"];
bool useDates = (bool)searchCriteria["dates"]["useDates"];

//sort
int sortId = (int)searchCriteria["sort"]["sortId"];
int sortType = (int)searchCriteria["sort"]["sortType"];
string sort = (string)searchCriteria["sort"]["sort"];
string sortOrder = (string)searchCriteria["sort"]["sortOrder"];

Mise à jour:

Comme recommandé j'ai ajouté

class SMSearchCriteria
    {
        public SMKeywords keywords { get; set; }
        public SMDates dates { get; set; }
        public SMClusters clusters { get; set; }
        public SMTaxonomies taxonomies { get; set; }
        public SMSort sort { get; set; }
    }

    class SMKeywords
    {
        public List<Dictionary<string, string>> AnyString {get; set;}
        public List<Dictionary<string, string>> AllString { get; set; }
        public List<Dictionary<string, string>> ExactString { get; set; }
        public List<Dictionary<string, string>> NotString { get; set; }
        public List<Dictionary<string, string>> HighlightString { get; set; } 
    }

    class SMDates
    {
        public string startDate { get; set; }
        public string endDate { get; set; }
        public bool useDates { get; set; }
    }

    class SMClusters
    {
        List<SMCluster> cluster;
    }

    class SMCluster
    {
        public Dictionary<string, string> cluster { get; set; }
    }

     class SMTaxonomies
    {
         public List<SMTaxonomy> taxonomies { get; set; }
    }

     class SMTaxonomy
     {
         public Dictionary<string, List<SMCategory>> taxonomy { get; set; }
     }

     class SMCategory
     {
         public Dictionary<int, string> category { get; set; }
     }

     class SMSort
    {
        public int sortId { get; set; }
        public int sortType { get; set; }
        public string sort { get; set; }
        public string sortOrder { get; set; }
    }

mais quand j'Execute:

    var mydata = JsonConvert.DeserializeObject<SMSearchCriteria>(contentSearchCriteria);

Je reçois l'exception:

[Newtonsoft.Json.JsonSerializationException] = {"Cannot deserialize JSON object into type 'System.Collections.Generic.List`1[System.Collections.Generic.Dictionary`2[System.String,System.String]]'."}

Mise à jour 2:

Comme je l'ai suggéré supprimé toutes les listes supplémentaires et a simplifié les classes à ceci:

class SearchMasterSearchCriteria
    {
        public SMKeywords keywords { get; set; }
        public SMDates dates { get; set; }
        public Dictionary<string, Dictionary<int, string>> clusters { get; set; } 
        public Dictionary<string, Dictionary<int, string>> taxonomies { get; set; } 
        public SMSort sort { get; set; }
    }

    class SMKeywords
    {
        public Dictionary<string, string> anyString {get; set;}
        public Dictionary<string, string> allString { get; set; }
        public Dictionary<string, string> exactString { get; set; }
        public Dictionary<string, string> notString { get; set; }
        public Dictionary<string, string> highlightString { get; set; } 
    }

    class SMDates
    {
        public string startDate { get; set; }
        public string endDate { get; set; }
        public bool useDates { get; set; }
    }

     class SMSort
    {
        public int sortId { get; set; }
        public int sortType { get; set; }
        public string sort { get; set; }
        public string sortOrder { get; set; }
    }

I code de test a également contribué à sérialiser l'objet comme ceci:

//criteria
            SearchMasterSearchCriteria smCriteria = new SearchMasterSearchCriteria();

            //keywords
            SMKeywords smKeywords = new SMKeywords(); ;
            Dictionary<string, string> dict = new Dictionary<string, string>();
            dict.Add("a5349f533e3aa3ccbc27de2638da38d6", "olympics");
            dict.Add("9cfa7aefcc61936b70aaec6729329eda", "games");
            smKeywords.allString = dict;

            //category
            Dictionary<int, string> categorieDict = new Dictionary<int, string>();
            categorieDict.Add(2488, "Olympics 2012 (not participation)");
            categorieDict.Add(8876, "Olympics and culture");

            //taxonomies
            Dictionary<string, Dictionary<int, string>> taxonomiesDict = new Dictionary<string, Dictionary<int, string>>();
            taxonomiesDict.Add("Topics", categorieDict);

            //metadata
            Dictionary<int, string> metadataDict = new Dictionary<int, string>();
            metadataDict.Add(1, @"private/n");

            //clusters
            Dictionary<string, Dictionary<int, string>> clustersDict = new Dictionary<string, Dictionary<int, string>>();
            clustersDict.Add("permission", metadataDict);


            //dates
            SMDates smDates = new SMDates();
            smDates.startDate = "15-01-2008";
            smDates.endDate = "15-09-2009";
            smDates.useDates = true;

            //sort
            SMSort smSort = new SMSort();
            smSort.sortId = 1;
            smSort.sortType = 2;
            smSort.sort = "datetime";
            smSort.sortOrder = "descending";

           //add to criteria.
            smCriteria.keywords = smKeywords;
            smCriteria.clusters = clustersDict;
            smCriteria.taxonomies = taxonomiesDict;
            smCriteria.dates = smDates;
            smCriteria.sort = smSort;

            //serialize
            string json = JsonConvert.SerializeObject(smCriteria);
            var mydata1 = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(json);

En ce moment-là la seule différence entre les 2 chaînes de JSON où. [] et pour les valeurs nulles anyString, exactString, etc. Donc, j'ai remplacé les crochets vides pour les bouclés et desearialized sans erreur:)

contentSearchCriteria = contentSearchCriteria.Replace("[]", "{}");
var mydata = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(contentSearchCriteria);
Était-ce utile?

La solution

Pour être honnête avec vous, je ne le font-ils comme vous le tout. Voici la façon dont je vais sur la récupération des données:

class Data {
     Dictionary<string, Dictionary<string, string>> keywords;
     DatesClass dates;
     .......

}

class DatesClass
{
    string startDate;
    string endDate;
    bool? useDates

}


var mydata = JsonConvert.DeserializeObject<Data>(jsonstring);

Je ne l'ai pas remplir toute la classe de données, mais vous obtenez le point. Je l'ai trouvé beaucoup plus facile de créer un objet dans la structure de vos données d'entrée et puis utilisez la méthode DeserializeObject pour remplir les données. Cela rend également le code beaucoup plus propre, et permet au compilateur de vérifier les fautes de frappe.

Autres conseils

Oui, votre question est maintenant de la manière JSON.net désérialise objets. Dans JSON.net une classe C # devient un objet JSON. Et un membre de cette classe devient une clé avec la valeur de l'élément de devenir la valeur.

Prenons l'exemple du chemin de taxonomie comme un exemple. En utilisant votre définition de classe ci-dessus JSON.net est à la recherche des données Json dans ce format:

{"taxonomies": {"taxonomies":[{"taxonomy": {"Topics": {1212, "foo"}}}]}

Cela ressemble rien du tout comme vos données d'entrée.

Lorsque vous créez vos objets pensent de cette façon.

1) un objet de base crée un {} dans le code json. 2) Un dictionnaire crée un {} dans le code JSON. 3) Une liste crée un [] dans le code JSON 4) tous les membres d'une classe crée une entrée dans le {} du code JSON

Ce qui pourrait aider à déboguer pour vous est de créer votre structure remplir certaines données temp puis utilisez JsonConvert.Serialize (myobj) pour vous montrer ce que JSON pense la structure ressemblera.

Je pense que votre exception vient d'avoir voie à de nombreuses classes.

Ceci est probablement ce que vous voulez que la partie de taxominies de votre code pour ressembler à:

class SMSearchCriteria
{
        public SMKeywords keywords { get; set; }
        public SMDates dates { get; set; }
        public SMClusters clusters { get; set; }
        public SMTaxominies taxonomies { get; set; }
        public SMSort sort { get; set; }
}

class SMTaxominies
{
    public Dictionary<string, string> Topics;
    public Keywords<string, string> Keywords;
}

Je voudrais commencer par une classe DTO fortement typée d'abord de préférence un DataContract de cette façon que vous obtenez le choix de sérialiser au format que vous voulez, à savoir JSON, Xml, Protobuf, etc.

Note: JSON est en fait assez lent à linéariser / désérialiser par rapport à la plupart des autres formats (voir: repères de sérialisation - JSON.NET est 'NewtonSoft.Json' ) Si vous faites une riche application client au lieu de l'application Web que vous pouvez choisir un format de sérialisation différent. Quel que soit le format que vous retrouvez avec, vous pouvez toujours réutiliser le même DTO, par exemple votre code ci-dessus serait ressemble à:

[DataContract]
public class MyDto
{
  [DataMember]
  public Keywords keywords { get; set; }
}

[DataContract]
public class Keywords
{
  [DataMember]
  public List<string> anyString { get; set; }

  [DataMember]
  public Dictionary<string,string> allString { get; set; }

  [DataMember]
  public List<string> exactString { get; set; }

  [DataMember]
  public List<string> notString { get; set; }

  [DataMember]
  public List<string> highlightString { get; set; }
}

var dto = new MyDto { Keywords = { allString = {{"a5349f533e3aa3ccbc27de2638da38d6", "olympics"}} };

var json = JsonConvert.SerializeObject(dto);
var fromJson = JsonConvert.DeserializeObject<MyDto>(json);

Modifier ajouté des liens

Il semble que vous pouvez avoir des problèmes avec JSON.NET dans ce cas, vous devriez essayer d'autres sérialiseurs JSON .NET / de-serializers. Microsoft navires inclus dans un System.Runtime.Serialization.Json.DataContractJsonSerializer v3.5 .NET. Voici quelques classes d'aide pour vous montrer comment sérialiser et désérialiser JSON.

Jayrock est une autre sérialiseur JSON pour .NET, mais il est plus lent que le reste et je le trouve n » t ont un bon support pour Generics.

Pourquoi utilisez-vous pas à LINQ JSON?

Par exemple, obtenir vos nœuds « de tri » mis en correspondance avec votre classe

var jsonResult = JObject.Parse(jsonString);

var sortItem = from s in jsonResult["sort"]
select new MySortObject{
                            SortId = s.Value<int>("sortId")
                        };

http://www.newtonsoft.com/json/help/html/ QueryJsonLinq.htm

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top