Deserialize JSON to a dictionary in C#

By FoxLearn 2/5/2025 8:28:12 AM   190
To deserialize JSON into a dictionary in C#, you can use the built-in JsonSerializer.Deserialize() method from the System.Text.Json namespace or use JsonConvert.DeserializeObject() from the popular Newtonsoft.Json library.

Deserialize to a Dictionary<string, string>

If the JSON has simple key-value pairs with string values, you can deserialize it into a Dictionary<string, string>.

{
    "Product": "Laptop",
    "Brand": "Dell",
    "Price": "1200"
}

To deserialize this JSON, use the built-in JsonSerializer.Deserialize() method from System.Text.Json and specify Dictionary<string, string> as the target type:

using System.Collections.Generic;
using System.Text.Json;

string json = "{ \"Product\": \"Laptop\", \"Brand\": \"Dell\", \"Price\": \"1200\" }";

var dictionary = JsonSerializer.Deserialize<Dictionary<string, string>>(json);

foreach(var (key, val) in dictionary)
{
    Console.WriteLine($"{key} = {val}");
}

This code will output:

Product = Laptop
Brand = Dell
Price = 1200

Deserialize a Nested Object to a Dictionary

When dealing with JSON objects that contain nested objects, you have a couple of options to deserialize:

  • Deserialize to Dictionary<string, class> where class represents the nested object.
  • Deserialize to a nested dictionary.

Deserialize to Dictionary<string, class>

If your JSON has nested objects, you can create a corresponding class for the nested structure.

{
  "Employee1": {
    "Name": "Alice",
    "Age": 30
  },
  "Employee2": {
    "Name": "John",
    "Age": 28
  }
}

You can create a Person class to represent the nested object:

public class Person
{
    public string Name { get; set; }
    public int Age { get; set; }
}

Then, deserialize the JSON into a Dictionary<string, Person> like this:

using System.Collections.Generic;
using System.Text.Json;

string json = "{ \"Employee1\": { \"Name\": \"Alice\", \"Age\": 30 }, \"Employee2\": { \"Name\": \"John\", \"Age\": 28 } }";

var dictionary = JsonSerializer.Deserialize<Dictionary<string, Person>>(json);

foreach (var (key, val) in dictionary)
{
    Console.WriteLine($"{key} = {val.Name}");
}

This will output:

Employee1 = Alice
Employee2 = John

Deserialize to a Nested Dictionary

If you don’t want to create a class, you can deserialize to a nested dictionary.

Consider this JSON:

{
  "Car1": {
    "Brand": "Toyota",
    "Model": "Corolla"
  },
  "Car2": {
    "Brand": "Ford",
    "Model": "Focus"
  }
}

You can deserialize it as follows:

using System.Collections.Generic;
using System.Text.Json;

string json = "{ \"Car1\": { \"Brand\": \"Toyota\", \"Model\": \"Corolla\" }, \"Car2\": { \"Brand\": \"Ford\", \"Model\": \"Focus\" } }";

var dictionary = JsonSerializer.Deserialize<Dictionary<string, Dictionary<string, string>>>(json);

foreach (var (key, nestedDictionary) in dictionary)
{
    Console.WriteLine(key);
    foreach(var (property, val) in nestedDictionary)
    {
        Console.WriteLine($"\t{property} = {val}");
    }
}

This outputs:

Car1
    Brand = Toyota
    Model = Corolla
Car2
    Brand = Ford
    Model = Focus

Deserialize to Dictionary<string, object>

If your JSON has properties with mixed data types (strings, integers, booleans), it’s recommended to either create a class for the structure or deserialize it into a Dictionary<string, object>. For this, you can use Newtonsoft.Json.

Consider this JSON with mixed data types:

{
  "Name": "Alice",
  "Age": 30,
  "IsEmployee": true
}

Using Newtonsoft.Json to deserialize:

using System.Collections.Generic;
using Newtonsoft.Json;

string json = "{ \"Name\": \"Alice\", \"Age\": 30, \"IsEmployee\": true }";

var dictionary = JsonConvert.DeserializeObject<Dictionary<string, object>>(json);

foreach (var (key, val) in dictionary)
{
    Console.WriteLine($"Key = {key}, Value = {val}, Type = {val.GetType().Name}");
}

This will output:

Key = Name, Value = Alice, Type = String
Key = Age, Value = 30, Type = Int32
Key = IsEmployee, Value = True, Type = Boolean

The reason Newtonsoft.Json is used here is because it correctly deserializes into the expected object types, which differs from System.Text.Json that would require extra steps to get the actual underlying values.