Handling missing members during JSON to C# deserialization and using JsonSerializerOptions

Rupen Anjaria
3 min readAug 4, 2024

--

In this article, we are going to see how to handle missing members during deserialization of JSON string to C# object. We will also explore how to use JsonSerializerOptions.

Note: You can try examples shown in this articles using your favorite online C# compiler like ShartLab.io.

Let’s say you are converting a JSON string to C# object. The JSON may be from API response or reading a file. However, if for some reason, provider of the JSON changes response and a new field is added then by default, deserialization will skip the new field and only map what is common between JSON and C# object.

However, what if we would like to handle this such that, may be, we can throw an exception or log a warning or just fail the conversion?

Look at this example, where properties are matching:

using System;
using System.Text.Json;

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

public class Program
{
public static void Main()
{

// JSON String
string jsonString = "{\"Name\":\"John\",\"Age\":30}";


// Deserialize from JSON
Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
}
}

Output:

Name: John, Age: 30

Now, let’s say the provider added a new field called Gender which will have value either “M” or “F”. By default, our code will work as it is. However, if you would like to throw an exception then we can use code below:

using System;
using System.Text.Json;
using System.Text.Json.Serialization;

[JsonUnmappedMemberHandling(JsonUnmappedMemberHandling.Disallow)]
public class Person
{
public string Name { get; set; }
public int Age { get; set; }
}

public class Program
{
public static void Main()
{

// JSON String
string jsonString = "{\"Name\":\"John\",\"Age\":30,\"Gender\":\"M\"}";


// Deserialize from JSON
Person deserializedPerson = JsonSerializer.Deserialize<Person>(jsonString);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
}
}

Here, we have imported a new namespace System.Text.Json.Serialization . From this namespace, we have use the enum: [JsonUnmappedMemberHandling(JsonUnmappedMemberHandling.Disallow)]

After above changes, if you try to compile then you should see System.Text.Json.JsonException with a message as “The JSON property ‘Gender’ could not be mapped to any .NET member contained in type ‘Person’.” This way, we can enforce strict matching of properties.

Using JsonSerializerOptions

The default method to serialize or deserialize works well for most of the cases, there are often times when we need to customize as per our need. This can be seamlessly achieved using specifying JsonSerializerOptions.

Let’s say while deserializing, we would like to enforce case sensitivity in property names. So, in our Person class example, string with property “Name” should convert successfully, however “name” should not be considered. (By default, the conversion is case-insensitive). Here is how we can achieve that:

using System;
using System.Text.Json;

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

public class Program
{
public static void Main()
{
Person person = new() { Name = "John", Age = 30 };
JsonSerializerOptions options = new()
{
WriteIndented = true,
PropertyNameCaseInsensitive = false
};

JsonSerializerOptions optionsCopy = new(options);

// Serialize to JSON
string jsonString = JsonSerializer.Serialize(person,optionsCopy);
Console.WriteLine(jsonString);

string strTest = "{\"name\":\"John\",\"Age\":31}";

// Deserialize from JSON
Person deserializedPerson = JsonSerializer.Deserialize<Person>(strTest, optionsCopy);
Console.WriteLine($"Name: {deserializedPerson.Name}, Age: {deserializedPerson.Age}");
}
}

We started by creating JsonSerializerOptionsobject and specified WriteIndented as trueand PropertyNameCaseInsensitiveas false. Note that, we can re-use the optionsobject and create new JsonSerializerOptions .

The WriteIndented will format our string nicely and PropertyNameCaseInsensitivewill make sure to ignore properties which are not matching.

Output:

{
"Name": "John",
"Age": 30
}
Name: , Age: 31

Using Defaults

JsonSerializerOptions also provides several defaults options. This includes defaults for web and mobile. In .NET 9 and later versions, you can use the JsonSerializerOptions.Web singleton to serialize with the default options that ASP.NET Core uses for web apps.

JsonSerializerOptions options = new(JsonSerializerDefaults.Web)

You can also overwrite some specific property of the option like:

JsonSerializerOptions options = new(JsonSerializerDefaults.Web)
{
WriteIndented = true
};

Conclusion

This article outlines how to handle missing property while serializing or deserializing — which can be useful if we are relying on that property. Further, we also explored several ways to customize serialization/deserialization mechanism using JsonSerializerOptions .

--

--

No responses yet