C Sharp, JavaScript Object Notation, flexible..

I’ve been working with JSON in .NET using Json.Net recently, going beyond simple serialization and deserialization. I want to document some useful techniques I’ve come across.

First, it’s important to differentiate between [JsonConvert](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_JsonConvert.htm) and [JObject](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Linq_JObject.htm), the two primary classes for handling JSON in .NET. When there’s a .NET class matching the JSON structure, JsonConvert.DeserializeObject is used. Otherwise, JObject.Parse deserializes into a JObject, which, combined with the dynamic keyword, allows for easy manipulation of the JSON structure. One point of confusion is that JsonConvert.DeserializeObject(item), JsonConvert.DeserializeObject(item) and JsonConvert.DeserializeObject(item) return a JObject, making a JObject.Parse() redundant in these cases: [equivalent](https://stackoverflow.com/questions/23645034/jobject-parse-vs-jsonconvert-deserializeobject).

The difference between camelCase in JSON and PascalCase in C# properties can be tricky. When deserializing with JsonConvert.DeserializeObject, Json.Net attempts to match JSON camelCase properties (like “{’name’:‘Iyan’}”) with either camelCase (Person.name) or PascalCase (Person.Name) properties in our .NET classes, eliminating the need to change standard naming conventions.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class PersonCamel
{
 public string name {get;set;}
 public int age {get;set;}
 public override string ToString()
 {
  return this.name + " - " + this.age;
 }
}

class Person
{
 public string Name {get;set;}
 public int Age {get;set;}
 public override string ToString()
 {
  return this.Name + " - " + this.Age;
 }
}

var jsonPerson = @"{
 'name':'Eric',
 'age': 49
}";

personCamel = JsonConvert.DeserializeObject<PersonCamel>(jsonPerson);
Console.WriteLine(personCamel.ToString());
//Eric - 49

person = JsonConvert.DeserializeObject<Person>(jsonPerson);
Console.WriteLine(person.ToString());
//Eric - 49 

By default, JsonConvert serializes C# class properties using their defined names, which could lead to PascalCase JSON. To ensure camelCase JSON output, we can guide the serializer using these techniques:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
JsonConvert.SerializeObject(person, new JsonSerializerSettings
{
 ContractResolver = new DefaultContractResolver
 {
  NamingStrategy = new CamelCaseNamingStrategy()
 }
});


JsonConvert.SerializeObject(person, new JsonSerializerSettings 
{ 
 ContractResolver = new CamelCasePropertyNamesContractResolver() 
});

Now, let’s explore JObject, dynamic, and explicit/implicit conversions. Let’s illustrate with code:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
var jsonResult = @"{
'result':'OK',
'users': [
 {
 'name':'xuan',
 'age': 45
 }, 
 {
 'name':'Francois',
 'age': 47
 }
  ]
}";

var jsonPerson = @"{
 'name':'Eric',
 'age': 49
}";

void TestJObjQuerying(string jsonResult, string jsonPerson)
{
 Console.WriteLine("TestJObjQuerying");
 
 dynamic resultJObj = JsonConvert.DeserializeObject(jsonResult);
 //to be able to use a linq query on the array we need to cast as JArray
 //then, as JArray implements IEnumerable of JToken we need to cast to dynamic again
 Console.WriteLine(String.Join(",", ((JArray)(resultJObj.users)).Select(it => (((dynamic)it).name))));
 
 
 
 dynamic personJObj = JObject.Parse(jsonPerson);
 
 var name1 = personJObj.name;
 Console.WriteLine(name1.GetType().Name);//JValue
 
 string name2 = personJObj.name; //implicit conversion
 Console.WriteLine(name2.GetType().Name); //string
 
 var name3 = (string)(personJObj.name); //explicit conversion
 Console.WriteLine(name3.GetType().Name);//string
 
 Func<dynamic, string> myFunc = jObj => jObj.name; //implicit conversion for the return type
 var name4 = myFunc(personJObj);
 Console.WriteLine(name4.GetType().Name);//string
 
}

TestJObjQuerying(jsonResult, jsonPerson); 

We know resultJObj.users is a JArray, but we need to explicitly cast it for the compiler, as it’s treated as dynamic. JArray doesn’t directly have a Select method; it’s an extension method from IEnumerable. Since extension methods and dynamic don’t work smoothly together, casting is needed so the compiler can correctly call Linq.Enumerable.Select. This Select method returns an IEnumerable, requiring another cast to dynamic for accessing the name property.

The following lines demonstrate how implicit and explicit conversions, combined with JObjects and dynamic, simplify working with JSON.

A while back, I came across [I already posted](https://deploytonenyures.blogspot.com/2015/10/deserialize-runtime-type.html) a fascinating concept: deserializing an object into a JObject and then converting a portion of it (for which we have a .NET type) using [ToObject](https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JToken_ToObject__1_1.htm). My previous example used a serializer with ToObject due to camelCase to PascalCase conversion. Still, as previously explained, JsonConvert handles this automatically now.

1
2
3
 dynamic obj = JObject.Parse(jsonResult);
 personJObject = obj.users[0];
 var person = personJObject.ToObject<Person>(); //camel to Pascal works good automatically 

The reverse can also be beneficial: taking a .NET class and serializing it to JSON with additional fields. This can be achieved with [FromObject](https://www.newtonsoft.com/json/help/html/Overload_Newtonsoft_Json_Linq_JToken_FromObject.htm) like this:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
var person = new Person{
 Name = "Jean",
 Age = 52
};
dynamic jPerson = JObject.FromObject(person);
jPerson.City = "Marseille";
Console.WriteLine(jPerson.ToString());
 
//{
//  "Name": "Jean",
//  "Age": 52,
//  "City": "Marseille"
//}

The limitation here is the lack of a built-in method to serialize the JObject to camelCase JSON. A more involved approach is required, similar to the one outlined [described here](https://stackoverflow.com/questions/40244395/how-to-serialize-a-jobject-the-same-way-as-an-object-with-json-net).

in this post

Licensed under CC BY-NC-SA 4.0
Last updated on May 01, 2024 12:13 +0100