Typed object to Json string - there and back again

The problem statement: how to turn object into Json string and back to typed object, without use of any implicit cast to any Type (or throw it off on some library)?
So we have classes like MessageA, MessageB, MessageC. We also have some communication medium, from which we receive some data:

{ messageType: "MessageB", message : "Hello" }

Now, how we can deserialize it to MessageB class, without using (e.g,):

MessageB messageB = JsonConvert.DeserializeObject<MessageB>(json);  

Of course we can create a map that stores (name, deserializer) pairs for every message. Final interface would be rather convenient like:

var mapper = new MessageMapper()  
                     .Add<YourMessageType>();

I've used this approach here, but I'm not completely happy with it.
If we already know that type (assembly that contains it is loaded), why should we specify it? Of course we can think about it as opt-in model and security feature (:P), but by default I would like to save some keyboard strokes here. Another reason is I wanted to use this for some routing mechanism between controller and actor system. Explicity declaring all messages' types is an overkill!

What I have used? JsonSerializerSettings with TypeNameHandling, and reflection with JObject.ToObject. Why reflection and ToObject method? The documentation specifies that we can use serializer settings and use $type param... but...

The "$type" mechanizm can be used to provide some additional security (nothing more)

... so we have to use some mapping mechanism anyway.

Turn message into string with type information

This part was actually the easiest.

var _serializerSettings = new JsonSerializerSettings  
            {
                PreserveReferencesHandling = PreserveReferencesHandling.Objects,
                TypeNameHandling = TypeNameHandling.Objects
            };
 var serializedMsg = JsonConvert.SerializeObject(msg, _serializerSettings);            

All you have to do is to specify the TypeNameHandling parameter, and $type="ExampleTypeName, Assembly" will be added to Json string.

Turn string into strongly typed object

  • Parse the object
JObject parsedObject = JObject.Parse(serializedMsg);  
  • Extract full type name
var fullType = (string)parsedMessage["$type"];  
  • Extract type name and assembly name
var typeName = fullType.Split(',')[0];  
var assemblyName = fullType.Split(',')[1].Trim();;  
  • Find type in loaded assemblies
var assemblies = AppDomain  
    .CurrentDomain
    .GetAssemblies();

if (assemblyName != null)  
{
    assemblies = assemblies
        .Where(assembly => assembly.FullName.Contains(assemblyName))
        .ToArray();
}

var foundType = assemblies  
    .Select(assembly => assembly.GetType(typeName))
    .First(type => type != null);
  • And finally cast object to the found type
var serializer = JsonSerializer.Create(_serializerSettings);  
var msgBack = parsedMessage.ToObject(foundType, serializer);  

We can check with msgBack.GetType it is indeed our type!

More "SOLID" code with some additional features like caching decorator is available here.