C# – Populate an existing object with JSON

Normally when you’re working with JSON, you deserialize it to a target type and get back an initialized and fully populated object. How about if you need to initialize an object yourself, and then populate it with JSON later?

For example, let’s say you want to load the following JSON array into a case-insensitive HashSet:

["hello", "Hello", "HELLO", "hi"]Code language: JSON / JSON with Comments (json)

To use a case-insensitive HashSet, you have to pass it a constructor parameter. To populate this existing object with JSON, you can use the Newtonsoft method JsonConvert.PopulateObject():

using Newtonsoft.Json;

var greetingSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

JsonConvert.PopulateObject(jsonArray, greetingSet);

//Just to show the populated object
Console.WriteLine(JsonConvert.SerializeObject(greetingSet, Formatting.Indented));
Code language: C# (cs)

This outputs the following:

[
  "hello",
  "hi"
]Code language: JSON / JSON with Comments (json)

Populating an existing object’s properties

In this example, I’ll show how to initialize an object with some of its properties populated, and then fill in the rest of the properties from JSON.

Consider the following JSON representing some properties in a Coder object:

{
   "Languages":[
      "C#",
      "Java"
   ],
   "YearsOfExperience":10
}Code language: JSON / JSON with Comments (json)

This is simple with Newtonsoft. Use JsonConvert.PopulateObject() to fill in the existing object’s properties:

using Newtonsoft.Json;

//Initialize some of the object's properties
var coder = new Coder()
{
    Id = 1,
    Name = "Bob"
};

//Fill in the remaining properties 
JsonConvert.PopulateObject(coderJson, coder);

//Just to show the fully populated object
Console.WriteLine(JsonConvert.SerializeObject(coder, Formatting.Indented));
Code language: C# (cs)

This outputs the following fully populated Coder object:

{
  "Id": 1,
  "Name": "Bob",
  "YearsOfExperience": 10,
  "Languages": [
    "C#",
    "Java"
  ]
}Code language: JSON / JSON with Comments (json)

System.Text.Json – Using JsonDocument to populate an existing object

At this time, System.Text.Json doesn’t have the direct equivalent of Newtonsoft’s PopulateObject() method. This is an open issue in the .NET GitHub repository, so it’s possible they’ll add it in the future.

Instead, you can use JsonDocument to parse JSON and map the values to the existing object. I’ll show examples below.

Populating a HashSet

Let’s say you want to load the following JSON array into a case-insensitive HashSet:

["hello", "Hello", "HELLO", "hi"]Code language: JSON / JSON with Comments (json)

Here’s how to use JsonDocument to parse and enumerate this JSON array so you can add the values to the existing HashSet object:

using System.Text.Json;

//Initialize object
var greetingSet = new HashSet<string>(StringComparer.OrdinalIgnoreCase);

//Populate it from JSON
using var jsonDoc = JsonDocument.Parse(jsonArray);
foreach (var jsonElement in jsonDoc.RootElement.EnumerateArray())
{
    greetingSet.Add(jsonElement.GetString());
}

//Note: Just to show the fully populated object
Console.WriteLine(JsonSerializer.Serialize(greetingSet, new JsonSerializerOptions() { WriteIndented = true }));
Code language: C# (cs)

This outputs the following:

[
  "hello",
  "hi"
]Code language: JSON / JSON with Comments (json)

Populating an existing object’s properties

Let’s say you have the following JSON containing a subset of properties for a GreatGeneral object:

{
   "Name":"Julius Caesar",
   "YearsOfExperience":10
}Code language: JSON / JSON with Comments (json)

The following code shows how to use JsonDocument to parse this JSON and loop through its properties. It maps the property values to the initialized GreatGeneral object based on the property name:

//Initialize object
var general = new GreatGeneral()
{
    Id = 1
};

//Fill in the remaining properties 
using var jsonDoc = JsonDocument.Parse(generalJson);
foreach (var jsonElement in jsonDoc.RootElement.EnumerateObject())
{
    switch (jsonElement.Name)
    {
        case nameof(GreatGeneral.Name):
            general.Name = jsonElement.Value.GetString();
            break;
        
        case nameof(GreatGeneral.YearsOfExperience):
            general.YearsOfExperience = jsonElement.Value.GetInt32();
            break;
    }
}

//Note: Just to show the fully populated object
Console.WriteLine(JsonSerializer.Serialize(general, new JsonSerializerOptions() {  WriteIndented = true }));
Code language: C# (cs)

Note: This has no error handling whatsoever. Be sure to handle errors based on your specific situation.

This outputs the following fully populated GreatGeneral object:

{
  "Id": 1,
  "Name": "Julius Caesar",
  "YearsOfExperience": 10
}Code language: JSON / JSON with Comments (json)

Leave a Comment