2014-05-14 19 views
37

Jaka jest różnica między JsonConvert.DeserializeObject i JObject.Parse? O ile mogę powiedzieć, obie biorą ciąg i znajdują się w bibliotece Json.NET. Jaka sytuacja sprawiłaby, że byłaby to wygodniejsza od drugiej, czy to głównie preferencje?JObject.Parse vs JsonConvert.DeserializeObject

Dla przykładu, oto przykład, w którym ja używam obu do zrobienia dokładnie tego samego - parsuj ciąg Json i zwróć listę jednego z atrybutów Json.

public ActionResult ReadJson() 
{ 
    string countiesJson = "{'Everything':[{'county_name':null,'description':null,'feat_class':'Civil','feature_id':'36865'," 
        +"'fips_class':'H1','fips_county_cd':'1','full_county_name':null,'link_title':null,'url':'http://www.alachuacounty.us/','name':'Alachua County'"+ ",'primary_latitude':'29.7','primary_longitude':'-82.33','state_abbreviation':'FL','state_name':'Florida'},"+ 
        "{'county_name':null,'description':null,"+ "'feat_class':'Civil','feature_id':'36866','fips_class':'H1','fips_county_cd':'3','full_county_name':null,'link_title':null,'url':'http://www.bakercountyfl.org/','name':'Baker County','primary_latitude':'30.33','primary_longitude':'-82.29','state_abbreviation':'FL','state_name':'Florida'}]}"; 

    //Can use either JSONParseObject or JSONParseDynamic here 
    List<string> counties = JSONParseObject(countiesJson); 
    JSONParseDynamic(countiesJson); 
    return View(counties); 
} 

public List<string> JSONParseObject(string jsonText) 
{ 
    JObject jResults = JObject.Parse(jsonText); 
    List<string> counties = new List<string>(); 
    foreach (var county in jResults["Everything"]) 
    { 
     counties.Add((string)county["name"]); 
    } 
    return counties; 
} 

public List<string> JSONParseDynamic(string jsonText) 
{ 
    dynamic jResults = JsonConvert.DeserializeObject(jsonText); 
    List<string> counties = new List<string>(); 
    foreach(var county in jResults.Everything) 
    { 
     counties.Add((string)county.name); 
    } 
    return counties; 
} 

Odpowiedz

40

API LINQ-JSON (JObject, JToken, itd.) Istnieje, aby umożliwić pracę z JSON bez konieczności znać jej strukturę z wyprzedzeniem. Można deserializować dowolny dowolny JSON przy użyciu JToken.Parse, a następnie zbadać jego zawartość i manipulować przy użyciu innych metod JToken. LINQ-to-JSON działa również dobrze, jeśli potrzebujesz tylko jednej lub dwóch wartości z JSON (takich jak nazwa hrabstwa).

JsonConvert.DeserializeObject, z drugiej strony, jest przeznaczony głównie do tego, abyś wiedział, że struktura JSON jest znana z wyprzedzeniem i chcesz deserializować na klasy o silnym typie. Na przykład, oto jak uzyskać pełny zestaw danych hrabstwa z twojego JSON na listę obiektów County.

class Program 
{ 
    static void Main(string[] args) 
    { 
     string countiesJson = "{'Everything':[{'county_name':null,'description':null,'feat_class':'Civil','feature_id':'36865'," 
       +"'fips_class':'H1','fips_county_cd':'1','full_county_name':null,'link_title':null,'url':'http://www.alachuacounty.us/','name':'Alachua County'"+ ",'primary_latitude':'29.7','primary_longitude':'-82.33','state_abbreviation':'FL','state_name':'Florida'},"+ 
       "{'county_name':null,'description':null,"+ "'feat_class':'Civil','feature_id':'36866','fips_class':'H1','fips_county_cd':'3','full_county_name':null,'link_title':null,'url':'http://www.bakercountyfl.org/','name':'Baker County','primary_latitude':'30.33','primary_longitude':'-82.29','state_abbreviation':'FL','state_name':'Florida'}]}"; 

     foreach (County c in JsonParseCounties(countiesJson)) 
     { 
      Console.WriteLine(string.Format("{0}, {1} ({2},{3})", c.name, 
       c.state_abbreviation, c.primary_latitude, c.primary_longitude)); 
     } 
    } 

    public static List<County> JsonParseCounties(string jsonText) 
    { 
     return JsonConvert.DeserializeObject<RootObject>(jsonText).Counties; 
    } 
} 

public class RootObject 
{ 
    [JsonProperty("Everything")] 
    public List<County> Counties { get; set; } 
} 

public class County 
{ 
    public string county_name { get; set; } 
    public string description { get; set; } 
    public string feat_class { get; set; } 
    public string feature_id { get; set; } 
    public string fips_class { get; set; } 
    public string fips_county_cd { get; set; } 
    public string full_county_name { get; set; } 
    public string link_title { get; set; } 
    public string url { get; set; } 
    public string name { get; set; } 
    public string primary_latitude { get; set; } 
    public string primary_longitude { get; set; } 
    public string state_abbreviation { get; set; } 
    public string state_name { get; set; } 
} 

Uwaga, Json.Net używa argumentu typu danej metody JsonConvert.DeserializeObject aby określić, jaki rodzaj obiektu utworzyć.

Oczywiście, jeśli nie zostanie określony typ podczas rozmowy DeserializeObject lub użyć object lub dynamic, następnie Json.Net nie ma wyboru, ale do deserializowania w JObject. (Można się przekonać, że zmienna dynamiczna faktycznie posiada wartość JObject, sprawdzając jResults.GetType().FullName.) W takim przypadku nie ma dużej różnicy między JsonConvert.DeserializeObject i JToken.Parse; albo da ci ten sam wynik.

+0

Dzięki za dobrze przemyślanej odpowiedzi! Obiekt i deskryptory dynamiczne mają teraz sens. Podany przykład jest również świetny - wygląda to znacznie łatwiej niż w przypadku JsonParseDynamic. – hubatish

+0

Bez problemu; cieszę się, że mogłem pomóc! –

+0

Chciałbym, żeby to było w [oficjalnych dokumentach] (http://www.newtonsoft.com/json/help/html/serializingjson.htm). –

11

JsonConvert.DeserializeObject ma jedną przewagę nad JObject.Parse: Możliwe jest użycie niestandardowych JsonSerializerSettings.

Może to być bardzo przydatne, np. jeśli chcesz kontrolować sposób deserializacji dat. Domyślnie daty są przekształcane do postaci DateTime. Oznacza to, że możesz skończyć datą z inną strefą czasową niż ta w łańcuchu json.

Możesz zmienić to zachowanie, tworząc JsonSerializerSetting i ustawiając DateParseHandling na DateParseHandling.DateTimeOffset.

Przykład:

var json = @"{ ""Time"": ""2015-10-28T14:05:22.0091621+00:00""}"; 
Console.WriteLine(json); 
// Result: { "Time": "2015-10-28T14:05:22.0091621+00:00" } 

var jObject1 = JObject.Parse(json); 
Console.WriteLine(jObject1.ToString()); 
// Result: { "Time": "2015-10-28T15:05:22.0091621+01:00" } 

var jObject2 = Newtonsoft.Json.JsonConvert.DeserializeObject(json, 
    new Newtonsoft.Json.JsonSerializerSettings 
    { 
    DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTimeOffset 
    }); 
Console.WriteLine(jObject2.ToString()); 
// Result: { "Time": "2015-10-28T14:05:22.0091621+00:00" }