Handling possible null value when converting JSON to C# class

Viewed 2671

I've run into an interesting problem when converting API data to a C# class in UWP.

I have an API that returns image dimensions, like this:

{
    "height": "25",
    "width": "25"
}

I also have a class with properties that match the JSON data, generated by json2csharp.com.

public class Image
{
    public int height { get; set; }
    public Uri url { get; set; }
    public int width { get; set; }
}

And I am converting the JSON to a C# class using something like this:

dynamic JsonData = JObject.Parse(JsonString);
Image img = JsonData.ToObject<Image>();

However, if the API does not know the height or width, it returns null instead of an int, like this:

{
    "height": null,
    "width": "25"
}

This obviously causes an exception to throw, specifically this error message:

Newtonsoft.Json.JsonSerializationException: Error converting value {null} to type 'System.Int32'

Is there some way to work around this or handle this scenario?

5 Answers

You can make an int nullable by adding a ?:

public class Image
{
    public int? height { get; set; }
    public Uri url { get; set; }
    public int? width { get; set; }
}

Other than json2csharp.com, QuickType can also help you do this:

public partial class Image
{
    [JsonProperty("height")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long? Height { get; set; }

    [JsonProperty("width")]
    [JsonConverter(typeof(ParseStringConverter))]
    public long Width { get; set; }
}

You have to add in the URL property yourself. QuickType also generates a bunch of other things for you as well, such as the ParseStringConverter custom JsonConverter.

If you're expecting null for your data, then use nullbale types. Change your class to:

public class Image {
    public int? height { get; set; }
    public Uri url { get; set; }
    public int? width { get; set; }
}

Another workable approach:

JsonConvert.SerializeObject(myObject, 
                            Newtonsoft.Json.Formatting.None, 
                            new JsonSerializerSettings { 
                                NullValueHandling = NullValueHandling.Ignore
                            });

I agree with the other answers that suggest nullable integers. This seems like the most clean approach. If nullable integers are no option, you could indeed try the NullValueHandling option and leave the integers at their default value. As a compliment to the other answers here, I have included a example that uses the NullValueHandling setting.

Fiddle (running example on dotnetfiddle)

Code

using System;
using Newtonsoft.Json;

public class Program
{
    private static string JsonWithNull = @"{ 'height': '25', 'width': null }";

    public static void Main()
    {
        var settings = new JsonSerializerSettings()
        {
            NullValueHandling = NullValueHandling.Ignore
        };

        Image image = JsonConvert.DeserializeObject<Image>(JsonWithNull, settings);

        Console.WriteLine("The image has a height of '{0}' and a width of '{1}'", image.height, image.width);
    }
}

public class Image
{   
    public int height { get; set; }
    public Uri url { get; set; }
    public int width { get; set; }
}

Consider Newtonsoft.Json.NullValueHandling.Ignore option.

Related