C# – Deserialize JSON to dynamic object

If you want to deserialize JSON without having to create a bunch of classes, use Newtonsoft.Json like this:

dynamic config = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());

Now you can use this object like any other object.

Example

Add the Newtonsoft.Json reference

Newtonsoft.JSON nuget package

Code

string json = "{\"endpoints\":[{\"name\":\"prod\",  \"enabled\":true },{\"name\":\"dev\", \"enabled\":true},{\"name\":\"qa\", \"enabled\":false}]}"; //see JSON section below for pretty printed JSON

dynamic config = JsonConvert.DeserializeObject<ExpandoObject>(json, new ExpandoObjectConverter());

Console.WriteLine($"Deserialized JSON into {config.GetType()}");

foreach (var enabledEndpoint in ((IEnumerable<dynamic>)config.endpoints).Where(t => t.enabled))
{
	Console.WriteLine($"{enabledEndpoint.name} is enabled");
}

Output:

JSON

{
  "endpoints": [
    {
      "name": "prod",
      "enabled": true
    },
    {
      "name": "dev",
      "enabled": true
    },
    {
      "name": "qa",
      "enabled": false
    }
  ]
}

Dynamic vs ExpandoObject

If you specify <dynamic> instead of <ExpandoObject> it’ll create a JObject.

In older versions of Newtonsoft, 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

This is no longer the case. You can use JObject just like ExpandoObject in new versions of Newtonsoft. However, I wanted to show a code example that will definitely work in whatever version of Newtonsoft you’re using.

Why cast to (IEnumerable<dynamic>)?

If you try to use config.endpoints.Where() like this:

foreach (var enabledEndpoint in config.endpoints.Where(t => t.enabled))

You’ll get the following compile error:

Cannot use a lambda expression as an argument to a dynamically dispatched operation without first casting it to a delegate or expression tree type.

This is why we have to cast it to (IEnumerable<dynamic>).

System.Text.Json vs Newtonsoft.Json

I tried to deserialize into a dynamic object using the built-in System.Text.Json, but it doesn’t work well. I tried it using .NET Core 3.1.

Example:

dynamic config = System.Text.Json.JsonSerializer.Deserialize<ExpandoObject>(json);

System.Text.Json deserializes this into an ExpandoObject with JsonElement properties. In my example, config.endpoints is a JsonElement. In order to loop over this, I’d have to use config.endpoints.EnumerateArray(). This returns JsonElement objects.

It’s JsonElements all the way down. In other words, this is not a nice clean way to deserialize JSON into a dynamic object.

Perhaps System.Text.Json will be improved later on, but as of right now, Newtonsoft.Json is better.

Go with Newtonsoft.Json.

Leave a Comment