C# – Deserialize JSON to dynamic object

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 cheeseCode language: plaintext (plaintext)

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? FalseCode 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.