Search code examples
c#jsonserializationjson.net

Determine type during json deserialize


I'm working on a protocol in which the receiver will receive json messages of certain specified custom types (currently 5, but could be 10-20). I'm struggling to come up with an optimal/fast solution which will automatically deserialize the json and return the correct type of object.

Example:

public class MessageA
{
    public string Message;
} 

public class MessageB
{
    public int value;
}

public class MessageC
{
    public string ValueA;
    public string ValueB;
}

Ideally, the method should be like

 Object Deserialize(string json);

and it will return one of the three message types OR null - in case there was a parsing error/the json didn't match any of the predefined type.

UPDATE: I have control over sender/receiver as well as the protocol design.


Solution

  • It would be helpful if the message could specify its type. Otherwise you have to infer it from some property or another.

    You could use a message wrapper class when serializing, like this:

    public class MessageWrapper<T>
    {
        public string MessageType { get { return typeof(T).FullName; } }
        public T Message { get; set; }
    }
    

    So if you have a class Name with a First and Last property, you could serialize it like this:

    var nameMessage = new MessageWrapper<Name>();
    nameMessage.Message = new Name {First="Bob", Last = "Smith"};
    var serialized = JsonConvert.SerializeObject(nameMessage);
    

    The serialized JSON is

    {"MessageType":"YourAssembly.Name","Message":{"First":"Bob","Last":"Smith"}}
    

    When deserializing, first deserialize the JSON as this type:

    public class MessageWrapper
    {
        public string MessageType { get; set; }
        public object Message { get; set; }
    }
    
    var deserialized = JsonConvert.DeserializeObject<MessageWrapper>(serialized);
    

    Extract the message type from the MessageType property.

    var messageType = Type.GetType(deserialized.MessageType);
    

    Now that you know the type, you can deserialize the Message property.

    var message = JsonConvert.DeserializeObject(
        Convert.ToString(deserialized.Message), messageType);
    

    message is an object, but you can cast it as Name or whatever class it actually is.