HeisenBerg HeisenBerg - 4 months ago 20
JSON Question

C# deserialize Json based on condition

{
"timeAgo": "6 minutes ago",
"time": "07/11/2016 07:00 AM",
"alertId": 145928,
"details": {


},
"priority": 10,
"type": 2,
"isClosed": 0,
"notesCount": 0,
"patientAccountId": 680,
"isRead": 0
}


I want to deserialize the json based on the int value 'type', in such as way, I want the details to be different types

public class Notification
{
public string timeAgo { get; set; }
public string time { get; set; }
public int alertId { get; set; }
public object details { get; set; }
public int priority { get; set; }
public int type { get; set; }
public int isClosed { get; set; }
public int notesCount { get; set; }
public int patientAccountId { get; set; }
public int isRead { get; set; }
}


if type = 1, then the object 'details' is of type A, if type = 2, 'details' is of type B and so on. There are about 25 values for type.

So, later I can do something like:

Notification n = ....
if (type == 1)
{
A a = (a) n.details;

Jim Jim
Answer

If your json does not have appropriate typing included in the JSON, this will work.

This may need tweaking if your actual structure is more complex, but I managed to get this to work on your sample.

var instance = Newtonsoft.Json.JsonConvert.DeserializeObject<Notification>(
    js,
    new ItemConverter());

public class ItemA : Item { }
public class ItemB : Item { }
public class Item { }

public class Notification
{
    public string timeAgo { get; set; }
    public string time { get; set; }
    public int alertId { get; set; }
    public Item details { get; set; }
    public int priority { get; set; }
    public int type { get; set; }
    public int isClosed { get; set; }
    public int notesCount { get; set; }
    public int patientAccountId { get; set; }
    public int isRead { get; set; }
}

public class ItemConverter : JsonConverter
{
    private Type currentType;
    public override bool CanConvert(Type objectType)
    {
        return typeof(Item).IsAssignableFrom(objectType) || objectType == typeof(Notification);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject item = JObject.Load(reader);
        if (item["type"] != null)
        {
            // save the type for later.
            switch (item["type"].Value<int>())
            {
                case 1:
                    currentType = typeof(ItemA);
                    break;
                default:
                    currentType = typeof(ItemB);
                    break;
            }
            return item.ToObject<Notification>();
        }

        // use the last type you read to serialise.
        return item.ToObject(currentType);
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}