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

c#, json, json.net, serialization

Solution

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)

Problem

I'm using Json.NET for a project I'm working on. From an external API, I am receiving JSON with properties that are objects, but when they are empty 'false' is passed. For example: ``` data: { supplier: { id: 15, name: 'TheOne' } } ``` Could also be: ``` data: { supplier: false } ``` How should I define the supplier property so that the supplier will be deserialized to a Supplier object or null. Right now I have: ``` public class Data { [JsonProperty("supplier")] public SupplierData Supplier { get; set; } } public class SupplierData { [JsonProperty("id")] public int Id { get; set; } [JsonProperty("name")] public string Name { get; set; } } ``` But now when trying to deserialize when supplier has a value of 'false' it fails. I would like the Supplier property to be null when the JSON value is 'false'. I hope someone knows how to do this. Thanks.

Original source

Related problems