Let’s say you have the following JSON:
{
"Name": "Bob",
"Pets": 2
}
Code language: JSON / JSON with Comments (json)
When you go to deserialize it, you notice that all or some of its properties are null (or default for value types):
using System.Text.Json;
var person = JsonSerializer.Deserialize<Person>(personJson);
Console.WriteLine($"{person.Name} has {person.Pets} pet(s)");
Code language: C# (cs)
This outputs the following (because person.Name is null and person.Pets is 0):
has 0 pet(s)
Code language: plaintext (plaintext)
The data is definitely there, so why did it set these properties to null / default? There are a few possibilities:
- Name mismatch due to casing difference or the names are completely different.
- The JSON field is missing.
- You have non-public setters. System.Text.Json only uses public setters.
The public setter requirement is kind of hidden, so it’s common to run into this problem accidently. If you use Quick Actions to generate properties, it adds internal setters, which leads to the null deserialization problem:
Go into the class and change these to public setters instead:
public class Person
{
public string Name { get; set; }
public int Pets { get; set; }
}
Code language: C# (cs)
Now when you deserialize, it’ll populate the properties as expected and will output:
Bob has 2 pet(s)
Code language: plaintext (plaintext)
When the JSON field is missing
Besides name mismatches preventing the property from getting populated during deserialization, the JSON field could simply be missing.
At this time, there’s nothing in System.Text.Json that’ll help you detect that. However, you can use the [Required] model validation attribute if you’re running into this problem in ASP.NET Core. It’ll detect that the required property is null during model validation and return an error response.
Newtonsoft handles this scenario better. It provides two options: 1) Use MissingMemberHandling.Error and/or 2) Use [JsonRequired] on your properties. I’ll show examples below.
Newtonsoft – Use MissingMemberHandling.Error
Use the MissingMemberHandling.Error setting to make Newtonsoft throw an exception if it can’t match a JSON field to a property.
using Newtonsoft.Json;
var jsonSettings = new JsonSerializerSettings()
{
MissingMemberHandling = MissingMemberHandling.Error
};
var person = JsonConvert.DeserializeObject<Person>(personJson, jsonSettings);
Code language: C# (cs)
Note: There’s an open issue about adding similar functionality to System.Text.Json. Hopefully this will get added.
This throws exceptions like this:
Newtonsoft.Json.JsonSerializationException: Could not find member ‘Name2’ on object of type ‘Person’.
Newtonsoft – Use [JsonRequired]
Add [JsonRequired] to your properties and it’ll throw an exception during deserialization if the property couldn’t be matched to a JSON field:
using Newtonsoft.Json;
public class Person
{
[JsonRequired]
public string Name { get; set; }
[JsonRequired]
public int Pets { get; set; }
}
Code language: C# (cs)
It’ll throw an exception like this:
Newtonsoft.Json.JsonSerializationException: Required property ‘Name’ not found in JSON.
Comments are closed.