If you want to deserialize JSON without having to create a bunch of classes, you can either deserialize to a dictionary or deserialize to a dynamic object with Newtonsoft.Json. Here’s an example. Let’s say you want to deserialize the following JSON:
{
"name":"Bob",
"favorites":{
"number":7,
"food":"cheese"
}
}
Code language: JSON / JSON with Comments (json)
To deserialize this to a dynamic object with Newtonsoft, use JsonConvert.DeserializeObject<dynamic>:
using Newtonsoft.Json;
var person = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine($"{person.name}'s favorite number is {person.favorites.number}")
Console.WriteLine($"{person.name}'s favorite food is {person.favorites.food}");
Code language: C# (cs)
This outputs the following:
Bob's favorite number is 7
Bob's favorite food is cheese
Code language: plaintext (plaintext)
Table of Contents
Deserialize to ExpandoObject in older versions of Newtonsoft
Before Newtonsoft v4.0.1 (released in 2014), specifying <dynamic> didn’t work. When you tried to access a dynamic property on JObject, you’d get an exception like this:
JObject does not contain a definition for property
If you’re using an older version of Newtonsoft (before v4.0.1):
- Use JsonConvert.DeserializeObject<ExpandoObject>
- Pass in ExpandoObjectConverter.
Here’s an example:
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
dynamic config = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());
Code language: C# (cs)
Example – Deserialize JSON array to dynamic object
Here’s another example of deserializing JSON to a dynamic object with Newtonsoft. Let’s say you’re deserializing JSON that contains an array of objects:
{
"version":1.0,
"endpoints": [
{
"name": "prod",
"enabled": true
},
{
"name": "dev",
"enabled": true
},
{
"name": "qa",
"enabled": false
}
]
}
Code language: JSON / JSON with Comments (json)
You can deserialize this to dynamic and loop over the array with a regular foreach:
using Newtonsoft.Json;
var apiConfig = JsonConvert.DeserializeObject<dynamic>(json);
Console.WriteLine($"Using api verison: {apiConfig.version}");
foreach(var endpoint in apiConfig.endpoints)
{
Console.WriteLine($"{endpoint.name} enabled? {endpoint.enabled}");
}
Code language: C# (cs)
This outputs the following:
Using api verison: 1
prod enabled? True
dev enabled? True
qa enabled? False
Code language: plaintext (plaintext)
Cast to IEnumerable<dynamic> to use Linq methods
If you want to use a Linq method on the dynamic object’s array, cast it to IEnumerable<dynamic> first, like this:
Console.WriteLine("Enabled endpoints:");
foreach (var enabledEndpoint in ((IEnumerable<dynamic>)apiConfig.endpoints).Where(t => t.enabled))
{
Console.WriteLine($"{enabledEndpoint.name}");
}
Code language: C# (cs)
This gets rid of compiler error CS1977 – Cannot use lambda expression as argument to dynamically dispatched… .
System.Text.Json vs Newtonsoft.Json
The built-in System.Text.Json doesn’t work well for deserializing to dynamic objects:
dynamic config = System.Text.Json.JsonSerializer.Deserialize<dynamic>(json);
Code language: C# (cs)
When you try to deserialize to dynamic or ExpandoObject, System.Text.Json deserializes it to JsonElement. This is fine if you want to work with JSON DOM (read: using JsonDocument and using JsonNode). However this defeats the purpose of deserializing to dynamic. For true dynamic support, stick with Newtonsoft.
Comments are closed.