C#: Deserializing JSON when one field can be different types

c#, deserialization, json

Solution

With JSON.NET you could write a custom JSON converter. For example you could have the following objects:

public class Root
{
    public string Status { get; set; }
    public Result Result { get; set; }
}

public class Result
{
    public bool? Value { get; set; }
    public Item[] Items { get; set; }
}

public class Item
{
    public string Name { get; set; }
    public string UserIdentifier { get; set; }
    public string MaxAccounts { get; set; }
}

and your JSON will be deserialized to a `Root[]`.

Here's how the custom JSON converter may look like:

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

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Boolean)
        {
            return new Result
            {
                Value = (bool)reader.Value,
            };
        }

        return new Result
        {
            Items = serializer.Deserialize<Item[]>(reader),
        };
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // If you want to support serializing you could implement this method as well
        throw new NotImplementedException();
    }
}

and then:

class Program
{
    static void Main()
    {
        var json = 
        @"[
            {
                ""status"": ""ok"",
                ""result"": true
            },
            {
                ""status"": ""ok"",
                ""result"": [
                    {
                        ""name"": ""John Doe"",
                        ""UserIdentifier"": ""abc"",
                        ""MaxAccounts"": ""2""
                    }
                ]
            }
        ]";

        var settings = new JsonSerializerSettings();
        settings.Converters.Add(new ResultConverter());
        Root[] root = JsonConvert.DeserializeObject<Root[]>(json, settings);
        // do something with the results here
    }
}

Problem

I am communicating with an API that returns JSON containing either true, false or an array of string arrays. I wish to deserialize this JSON and store the boolean value, if there is one, in a class field called Success of data type bool, and the array, if there is one, in a field called Result of a custom data type. What is the best to go about achieving this? Some JSON: ``` [ {"status":"ok","result":true}, { "status":"ok", "result": [ {"name":"John Doe","UserIdentifier":"abc","MaxAccounts":"2"} ] } ] ``` My Result class: ``` class Result { string Name, string UserIdentifier, string MaxAccounts } ``` Class for communicating with the Api: ``` class Api { public string Status { get; set; } public Result[] Result { get; set; } public bool Success { get; set; } } ```

Original source