I have the following JSON:
{
"countries": [
{
"name": "Afghanistan",
"alternative_names": [],
"formal_name": "Islamic Republic of Afghanistan",
"the_prefix": false,
"in_un": true
}
]
}
The following classes:
[Serializable]
public class CountriesData
{
public List<CountryData> countries;
}
[Serializable]
public class CountryData
{
/// <summary>
/// The informal name of the country.
/// <example>
/// E.g. China
/// </example>
/// </summary>
public string name;
/// <summary>
/// A <c>List<string></c> containing other informal names for the country.
/// <example>
/// E.g. for Myanmar, an alternative name is Burma.
/// </example>
/// </summary>
public List<string> alternative_names;
/// <summary>
/// The formal name of the country.
/// <example>
/// E.g. People's Republic of China
/// </example>
/// </summary>
public string formal_name;
/// <summary>
/// Should the word "the" come before this country's informal name?
/// <example>
/// E.g. for China, Spain, France, no. For (the) Gambia, (the) United Kingdom, (the) United States of America, yes.
/// </example>
/// </summary>
public bool the_prefix;
/// <summary>
/// Is this country a UN member state?
/// <example>
/// E.g. for China, Spain, France, yes. For Kosovo, no.
/// </example>
/// </summary>
public bool in_un;
}
and I am running the line of code:
CountriesData data = JsonSerializer.Deserialize<CountriesData>(jsonString);
This is resulting in null
. I have tested and the string jsonString
does correctly contain above JSON as a string. No matter what I have tried, this always returns null
.
I am getting the warning Warning CS8601 Possible null reference assignment.
on this line of code.
Why is this not deserializing properly?
I'll explain using the code from this Fiddle:
Your model classes contain public fields. Fields are by default ignored in serialization/deserialization.
... By default, fields are ignored.
Citation from Serialization behavior
Instead, use properties (easiest method) as shown in the code below. You can force serialization of fields, though if you so absolutely want.
A second factor is naming:
The recommended naming in json and C# differ. There are different ways to mitigate that. One of those is shown in below code: you can specify a name that is used in json that is supposed to be mapped to a specific property.
using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;
public class Program
{
public static void Main()
{
var jsonString = @"
{
""countries"": [
{
""name"": ""NonControversialNationName"",
""alternative_names"": [],
""formal_name"": ""NonControversial Republic of NonControversistan"",
""the_prefix"": false,
""in_un"": true
}
]
}
";
var obj = JsonSerializer.Deserialize<CountriesData>(jsonString);
obj.Dump();
}
}
public class CountriesData
{
[JsonPropertyName("countries")]
public List<CountryData> Countries {get; set;}
}
public class CountryData
{
[JsonPropertyName("name")]
public string Name {get; set;}
[JsonPropertyName("alternative_names")]
public List<string> AlternativeNames {get; set;}
[JsonPropertyName("formal_name")]
public string FormalName {get; set;}
[JsonPropertyName("the_prefix")]
public bool Prefix {get; set;}
[JsonPropertyName("in_un")]
public bool IsUnMember {get; set;}
}
Output:
Dumping object(CountriesData) Countries : [ { AlternativeNames : [] FormalName : NonControversial Republic of NonControversistan IsUnMember : True Name : NonControversialNationName Prefix : False } ]
About that CS8601
Warning: That depends if you are in a Nullable enabled environment.
You probably might need to use CountriesData? data = JsonSerializer.Deserialize<CountriesData>(jsonString);
(mind the "?")