JObject.Parse vs JsonConvert.DeserializeObject
Solution 1:
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.
Solution 2:
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" }