سؤال

أنا أحاول استخدام إطار عمل json.net في نموذج Windows لقراءة بعض المعلومات من سلسلة JSON. لكن أنا أعاني من أجل الحصول على القواميس من مجموعة "التصنيفات-> المواضيع" و "المجموعات"

{
    "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"
    }
}

باستخدام الرمز ، تمكنت من قراءة بعض المعلومات.

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"];

تحديث:

كما أوصت أضفت

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; }
    }

لكن عندما أقوم بتنفيذ:

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

أحصل على الاستثناء:

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

تحديث 2:

كما هو مقترح ، قمت بإزالة جميع القوائم الإضافية وتبسيط الفصول على هذا:

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; }
    }

أضفت أيضًا رمز الاختبار لتسلسل الكائن مثل هذا:

//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);

بحلول ذلك الوقت ، الفرق الوحيد بين سلاسل JSON 2 حيث. [] و Nulls for anystring ، acctstring ، وما إلى ذلك. لذلك استبدلت الأقواس المربعة الفارغة للأقواس المجعد وتهرب من عدم وجود أخطاء :)

contentSearchCriteria = contentSearchCriteria.Replace("[]", "{}");
var mydata = JsonConvert.DeserializeObject<SearchMasterSearchCriteria>(contentSearchCriteria);
هل كانت مفيدة؟

المحلول

لأكون صادقًا معك ، لن أفعل ذلك ، فهي تفعل ذلك على الإطلاق. ها هي الطريقة التي سأذهب بها لاسترداد البيانات:

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

}

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

}


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

لم أملأ فئة البيانات بأكملها ، لكنك تحصل على هذه النقطة. لقد وجدت أنه من الأسهل بكثير إنشاء كائن في بنية بيانات الإدخال الخاصة بك ثم استخدام طريقة DeserializeObject لملء البيانات. هذا أيضًا يجعل الكود أكثر نظافة ، ويسمح للمترجم بالتحقق من الأخطاء المطبعية.

نصائح أخرى

نعم ، مشكلتك الآن هي في الطريقة التي يفرغ بها json.net الكائنات. في json.net ، يصبح فئة C# كائن JSON. ويصبح أحد أعضاء تلك الفئة مفتاحًا مع أن تصبح قيمة العضو القيمة.

دعنا نأخذ مثال مسار التصنيف كمثال. باستخدام تعريف الفئة أعلاه json.net يبحث عن بيانات JSON في هذا التنسيق:

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

هذا لا يبدو على الإطلاق مثل بيانات الإدخال الخاصة بك.

عندما تقوم بإنشاء الأشياء الخاصة بك ، فكر في الأمر بهذه الطريقة.

1) يقوم كائن أساسي بإنشاء {} في رمز JSON. 2) يقوم القاموس بإنشاء {} في رمز JSON. 3) تنشئ القائمة [] في رمز JSON 4) يقوم كل عضو في فئة بإنشاء إدخال في {} من رمز JSON

ما قد يساعد في تصحيح هذا الأمر من أجلك هو إنشاء هيكلك ، وملء بعض بيانات Temp ثم استخدم jsonconvert.serialize (myobj) لتظهر لك ما يعتقد Json أن الهيكل سيبدو عليه.

أعتقد أن استثناءك يأتي من الطريق إلى العديد من الفصول الدراسية.

ربما يكون هذا ما تريد أن يبدو عليه جزء من الكود الخاص بك:

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;
}

أود أن أبدأ مع فئة DTO القوية من النوع الذي يفضل أولاً التعاقد على البيانات بهذه الطريقة ، يمكنك الحصول على خيار لتسلسله بأي تنسيق تريده ، أي JSON ، XML ، Protobuf ، إلخ.

ملاحظة: JSON في الواقع بطيئة جدًا في التسلسل/إزالة التسلسل مقارنة بمعظم التنسيقات الأخرى (انظر: معايير التسلسل - json.net هو 'newtonsoft.json') إذا كنت تقوم بتطبيق عميل غني بدلاً من تطبيق الويب مما قد ترغب في اختيار تنسيق تسلسل مختلف. بغض النظر عن التنسيق الذي ينتهي به الأمر ، لا يزال بإمكانك إعادة استخدام نفس DTO ، على سبيل المثال ، فإن الكود الخاص بك أعلاه سيبدو مثل:

[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);

تعديل: روابط إضافية

يبدو أنك قد تواجه مشاكل مع json.net في هذه الحالة يجب أن تجرب مسلسلات json الأخرى .NET/defializers. Microsoft تشحن system.runtime.serialization.json.datacontractjsonserializer المدرجة في .NET v3.5. إليك بعض فصول المساعد التي توضح لك كيفية ذلك التسلسل و إلغاء التالي جيسون.

جايرووك هو مسلسل JSON آخر لـ .NET ، لكنه أبطأ من الباقي وأجد أنه لا يتمتع بدعم جيد للوظائف العامة.

لماذا لا تستخدم LINQ إلى JSON؟

على سبيل المثال ، تم تعيين العقد "الفرز" الخاص بك إلى فصلك

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

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top