Why is deserializing this JSON resulting in `null`?

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?

>Solution :

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 "?")

Leave a Reply