114

What's the difference between JsonConvert.DeserializeObject and JObject.Parse? As far as I can tell, both take a string and are in the Json.NET library. What kind of situation would make one more convenient than the other, or is it mainly just preference?

For reference, here's an example of me using both to do exactly the same thing - parse a Json string and return a list of one of the Json attributes.

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;
}
abatishchev
101k88 gold badges303 silver badges443 bronze badges
asked May 14, 2014 at 3:13
0

5 Answers 5

142

The LINQ-to-JSON API (JObject, JToken, etc.) exists to allow working with JSON without needing to know its structure ahead of time. You can deserialize any arbitrary JSON using JToken.Parse, then examine and manipulate its contents using other JToken methods. LINQ-to-JSON also works well if you just need one or two values from the JSON (such as the name of a county).

JsonConvert.DeserializeObject, on the other hand, is mainly intended to be used when you DO know the structure of the JSON ahead of time and you want to deserialize into strongly typed classes. For example, here's how you would get the full set of county data from your JSON into a list of County objects.

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

Notice that Json.Net uses the type argument given to the JsonConvert.DeserializeObject method to determine what type of object to create.

Of course, if you don't specify a type when you call DeserializeObject, or you use object or dynamic, then Json.Net has no choice but to deserialize into a JObject. (You can see for yourself that your dynamic variable actually holds a JObject by checking jResults.GetType().FullName.) So in that case, there's not much difference between JsonConvert.DeserializeObject and JToken.Parse; either will give you the same result.

answered Jul 9, 2014 at 4:47
7
  • Thanks for the well-thought out answer! The Object vs Dynamic descriptors make sense now. The example you give is also great - that looks much easier than it would be with JsonParseDynamic. Commented Jul 9, 2014 at 15:49
  • 3
    I wish this was in the official docs. Commented Mar 1, 2016 at 2:57
  • 1
    Is DeserializeObject tolerant to extra properties in json, that do not exist in the class. Will it ignore them or throw exception? Commented Jul 26, 2016 at 10:43
  • 1
    @MichaelFreidgeim It is controlled by the MissingMemberHandling setting. The default is to ignore extra properties. Commented Jul 26, 2016 at 13:34
  • Performance-wise, is deserializing to a dynamic object going to be slower or quicker, on average, than deserializing it to a strongly-typed class? I can see different reasons for one being faster than the other, but I wonder if using dynamic could be faster because it doesn't have to use reflection? Commented Oct 6, 2017 at 14:32
39

JsonConvert.DeserializeObject has one advantage over JObject.Parse: It is possible to use custom JsonSerializerSettings.

This can be very useful e.g. if you want to control how dates are deserialized. By default dates are deserialized into DateTime objects. This means that you may end up with a date with another time zone than the one in the json string.

You can change this behaviour by creating a JsonSerializerSetting and setting DateParseHandling to DateParseHandling.DateTimeOffset.

An example:

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" }
answered Oct 28, 2015 at 14:12
1
  • Shouldn't it also be faster to use DeserializeObject if you know exactly which class you're going to (i.e., not dynamic)? Commented Nov 22, 2018 at 1:23
2

For me the key difference I was interested in was Speed.

I made a simple test to find out if it was faster to use JToken.Parse(string) or DeserializeObject<JToken>(string) to create a large amount of JToken and these were the results after 2,000,000 iterations using a sample of real world data

Method Operating System Ticks Milliseconds
JsonConvert 86123945 8612ms
JToken 67671724 6767ms

There was some variation between runs but the difference was always large.

Here is the test so you can modify it or run it yourself:

 private static string s = @"{'stream':'btcusdt @bookTicker','data':{'u':20430107433,'s':'BTCUSDT','b':'21223.72000000','B':'3.29440000','a':'21223.73000000','A':'2.05450000'}}";
 private static Stopwatch sw = new Stopwatch();
 private static void Main(string[] args)
 {
 JToken convert = default;
 sw.Restart();
 for (int i = 0; i < 2000000; i++)
 {
 convert = JsonConvert.DeserializeObject<JToken>(s);
 }
 Console.WriteLine("JsonConvert: " + sw.ElapsedTicks + " [" + sw.ElapsedMilliseconds + "ms]");
 convert.ToString();
 convert = default;
 sw.Restart();
 for (int i = 0; i < 2000000; i++)
 {
 convert = JToken.Parse(s);
 }
 Console.WriteLine("JToken : " + sw.ElapsedTicks + " [" + sw.ElapsedMilliseconds + "ms]");
 convert.ToString();
 Console.ReadLine();
 }
answered Jun 25, 2022 at 5:30
0

I knew an advantage that JsonConvert.DeserializeObject can deserialize an Array/List json text directly, but JObject cannot.

Try below sample code:

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
namespace NetCoreJsonNETDemo
{
 internal class Person
 {
 [JsonProperty]
 internal string Name
 {
 get;
 set;
 }
 [JsonProperty]
 internal int? Age
 {
 get;
 set;
 }
 }
 internal class PersonContainer
 {
 public List<Person> Persons
 {
 get;
 set;
 }
 }
 class Program
 {
 static T RecoverPersonsWithJsonConvert<T>(string json)
 {
 return JsonConvert.DeserializeObject<T>(json);
 }
 static T RecoverPersonsWithJObejct<T>(string json) where T : class
 {
 try
 {
 return JObject.Parse(json).ToObject<T>();
 }
 catch (Exception ex)
 {
 Console.WriteLine("JObject threw an Exception: " + ex.Message);
 return null;
 }
 }
 static void Main(string[] args)
 {
 List<Person> persons = new List<Person>();
 persons.Add(new Person()
 {
 Name = "Jack",
 Age = 18
 });
 persons.Add(new Person()
 {
 Name = "Sam",
 Age = null
 });
 persons.Add(new Person()
 {
 Name = "Bob",
 Age = 36
 });
 string json = JsonConvert.SerializeObject(persons, new JsonSerializerSettings()
 {
 Formatting = Formatting.Indented
 });
 List<Person> newPersons = RecoverPersonsWithJsonConvert<List<Person>>(json);
 newPersons = RecoverPersonsWithJObejct<List<Person>>(json);//JObject will throw an error, since the json text is an array.
 PersonContainer personContainer = new PersonContainer()
 {
 Persons = persons
 };
 json = JsonConvert.SerializeObject(personContainer, new JsonSerializerSettings()
 {
 Formatting = Formatting.Indented
 });
 newPersons = RecoverPersonsWithJObejct<PersonContainer>(json).Persons;
 newPersons = null;
 newPersons = RecoverPersonsWithJsonConvert<PersonContainer>(json).Persons;
 Console.WriteLine("Press any key to end...");
 Console.ReadKey();
 }
 }
}
answered Jan 10, 2020 at 10:04
2
  • 2
    JToken.Parse() can :) Commented Feb 5, 2020 at 7:59
  • 1
    @FrodeNilsen Also, JToken.Parse() appears to be the fastest of all the dynamic/deserialization methods on this page, according to my tests. Commented May 27, 2020 at 16:17
0

Apart from the answers provided here around usage, which are correct as per me : Jobject.Parse -> when the Json is not strongly Typed or you do not know the structure of Json ahead of time

JsonConvert.DeserializeObject<T> -> When you know which class or type to cast the Json in. T can be a complex class or a simple type

My answer is based on the performance in case where the structure is not known, as given in the OP code, if we benchmark the usage of both methods for performance, it is observed that Jobject.Parse() fares well in terms of allocated memory, please ignore the name of methods, I am first calling the method with 'JsonConvert.DeserializeObject' and then second method is with Jobject.Parse

enter image description here

answered Mar 4, 2020 at 4:15
1
  • Are you deserializing to a JObject in both cases? Commented Jul 23, 2021 at 4:54

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.