JObject.Parse vs JsonConvert.DeserializeObject

В чем разница между JsonConvert.DeserializeObject и JObject.Parse? Насколько я могу судить, оба берут строку и находятся в библиотеке Json.NET. Какая ситуация сделала бы более удобной, чем другая, или в основном это предпочтение?

Для справки, здесь пример того, как я использую оба, чтобы сделать то же самое - проанализируйте строку Json и верните список одного из атрибутов 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;
}

Ответ 1

API LINQ-to-JSON (JObject, JToken и т.д.) существует, чтобы позволить работать с JSON без необходимости знать его структуру раньше времени. Вы можете десериализовать любой произвольный JSON с помощью JToken.Parse, а затем изучить и обработать его содержимое с помощью других методов JToken. LINQ-to-JSON также хорошо работает, если вам просто нужно одно или два значения из JSON (например, имя округа).

JsonConvert.DeserializeObject, с другой стороны, в основном предназначен для использования, когда вы знаете структуру JSON раньше времени, и вы хотите десериализовать себя в строго типизированные классы. Например, здесь вы можете получить полный набор данных графства из вашего JSON в список объектов 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; }
}

Обратите внимание, что Json.Net использует аргумент типа, присвоенный методу JsonConvert.DeserializeObject, чтобы определить тип создаваемого объекта.

Конечно, если вы не укажете тип при вызове DeserializeObject или используете object или dynamic, тогда у Json.Net нет выбора, кроме как десериализоваться в JObject. (Вы сами можете убедиться, что ваша динамическая переменная действительно содержит JObject, проверив jResults.GetType().FullName.) Таким образом, в этом случае разница между JsonConvert.DeserializeObject и JToken.Parse невелика; либо даст вам тот же результат.

Ответ 2

JsonConvert.DeserializeObject имеет одно преимущество над JObject.Parse: Можно использовать пользовательские настройки JsonSerializerSettings.

Это может быть очень полезно, например. если вы хотите контролировать, как даты десериализованы. По умолчанию даты десериализуются в объекты DateTime. Это означает, что вы можете указать дату с другим часовым поясом, кроме даты в строке json.

Вы можете изменить это поведение, создав JsonSerializerSetting и настройки DateParseHandling to DateParseHandling.DateTimeOffset.

Пример:

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