How to deserialize a JSON property that can be two different data types using Json.NET

This can be solved by making a custom JsonConverter for your SupplierData class. Here is what the converter might look like:

class SupplierDataConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(SupplierData));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Object)
        {
            return token.ToObject<SupplierData>();
        }
        return null;
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

To use it, all you would need to do is add a [JsonConverter] attribute to the Supplier property in your Data class like this:

public class Data
{
    [JsonProperty("supplier")]
    [JsonConverter(typeof(SupplierDataConverter))]
    public SupplierData Supplier { get; set; }
}

Below is a demonstration of the converter in action. Note that the demo assumes you have some kind of containing object for the data property, since the JSON in your question can’t stand on its own. I defined a class called RootObject for this purpose:

public class RootObject
{
    [JsonProperty("data")]
    public Data Data { get; set; }
}

The actual demo code follows:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""data"": 
            {
                ""supplier"": 
                {
                    ""id"": 15,
                    ""name"": ""TheOne""
                }
            }
        }";

        Console.WriteLine("--- first run ---");
        RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
        DumpSupplier(obj.Data.Supplier);

        json = @"
        {
            ""data"": 
            {
                ""supplier"": false
            }
        }";

        Console.WriteLine("--- second run ---");
        obj = JsonConvert.DeserializeObject<RootObject>(json);
        DumpSupplier(obj.Data.Supplier);
    }

    static void DumpSupplier(SupplierData supplier)
    {
        if (supplier != null)
        {
            Console.WriteLine("Id: " + supplier.Id);
            Console.WriteLine("Name: " + supplier.Name);
        }
        else
        {
            Console.WriteLine("(null)");
        }
        Console.WriteLine();
    }
}

And here is the output from the above:

--- first run ---
Id: 15
Name: TheOne

--- second run ---
(null)

Leave a Comment