1

I want to deserialize json messages via json.net, and I have the following json object (which might not be optimal!!!)

{
  "deviceId":"XXXX",
  "messages":
  [
    {
      "type":"messageType1",
      "version":1,
      "content":
      {
        "propertyA":"ValueA"
      }
    },
    {
      "type":"messageType2",
      "version":1,
      "content":
      {
        "propertyB":"ValueB"
      }
    }
  ]
}

Would it be possible to use a "CustomCreationConverter" for that?

I was hoping to use "type" for detection of correct class...

BR Martin

------------ UPDATE -----------------

I have now implemented the following solution, and would appreciate any feedback.

public class MessageType1
{
  public string PropertyA{ get; set; }
}

public class MessageType2
{
  public string PropertyB{ get; set; }
}

public abstract class MessageEntity
{
  [JsonConverter(typeof(ContentConverter))]
  abstract public string Type { get; set; }
  abstract public int Version { get; set; }
}

public class Type1MessageEntity : MessageEntity
{
  override public string Type { get; set; }
  override public int Version { get; set; }
  public Type1Message Content { get; set; }
}

public class Type2MessageEntity : MessageEntity
{
  override public string Type { get; set; }
  override public int Version { get; set; }
  public Type2Message Content { get; set; }
}

public sealed class ContentConverter : JsonConverter
{
  public override bool CanConvert(Type objectType)
  {
    return typeof(MessageEntity).IsAssignableFrom(objectType);
    throw new NotImplementedException();
  }

  public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
  {
    JObject jObject = JObject.Load(reader);

    // Try to parse basic information from object
    string type = (string)jObject["type"].ToObject<string>();
    int version = (int)jObject["version"].ToObject<int>();
    JToken contentValue;

    try
    {
      type = (string)jObject["type"].ToObject<string>();
      version = (int)jObject["version"].ToObject<int>();
      contentValue = jObject["content"];
    }
    catch
    {
      throw new JsonSerializationException($"Incorrect format");
    }

    // Try to parse content
    MessageEntity messageEntity = null;

    try
    {
      switch (type)
      {
        case "messageType1":
        {
          messageEntity = new Type1MessageEntity();
          messageEntity.Type = type;
          messageEntity.Version = version;
          (messageEntity as Type1MessageEntity).Content = contentValue.ToObject<Type1Message>(serializer);
          break;
        }
        case "messageType2":
        {
          messageEntity = new Type2MessageEntity();
          messageEntity.Type = type;
          messageEntity.Version = version;
          (messageEntity as Type2MessageEntity).Content = contentValue.ToObject<Type2Message>(serializer);
          break;
        }
        default:
        {
          throw new JsonSerializationException($"Unsupported type: '{type}'");
        }
      }
    }
    catch
    {
      throw new JsonSerializationException($"Incorrect content format");
    }

    return messageEntity;
  }

  public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
  {
    throw new NotImplementedException();
  }
}
Martin
  • 23
  • 3
  • Something like this maybe? [How to conditionally deserialize JSON object based on another JSON property?](https://stackoverflow.com/q/38357864/3744182). – dbc Feb 22 '17 at 19:49
  • @dbc Thanks. I have updated the question with a solution, which I would like some feedback on. I am not for sure about, if the code "looks" nice :-) Thanks! – Martin Feb 23 '17 at 10:54

0 Answers0