So I have two classes like the ones below. They are both in the same namespace and in the same shared project.
public class Person{
public string Name{get;set;}
}
public class EmployedPerson : Person{
public string JobTitle{get;set;}
}
When I serilize these items into rabbitmq I am serializing as the base class like so:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects
};
JsonConvert.SerializeObject(input, settings)
However when deserializing I run into issues. I would like to be able to do something like shown below where I deserialize as the base class and then check if it is a inheirited type.
Type check:
Person person = Deserialize<Person>(e.Body, Encoding.Unicode);
if (person is EmployedPerson)
{
logger.LogInformation("This person has a job!");
}
Deserialize settings:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Auto
};
Deserialize logic:
private static T Deserialize<T>(byte[] data, Encoding encoding) where T : class
{
try
{
using (MemoryStream stream = new MemoryStream(data))
using (StreamReader reader = new StreamReader(stream, encoding))
return JsonSerializer.Create(settings).Deserialize(reader, typeof(T)) as T;
}
catch (Exception e)
{
Type typeParameter = typeof(T);
logger.LogError(LogEvent.SERIALIZATION_ERROR, e, "Deserializing type {@TypeName} failed", typeParameter.Name);
logger.LogInformation(Encoding.UTF8.GetString(data));
return default(T);
}
}
Result: The above code fails because the $type property contains the Assembly name and on each end of rabbitmq the assembly name is different because the classes are inside a shared project.
Example error:
Newtonsoft.Json.JsonSerializationException: Error resolving type specified in JSON 'Shared.Objects.EmployedPerson, Person.Dispatcher'. Path '$type', line 1, position 75. ---> System.IO.FileNotFoundException: Could not load file or assembly 'Person.Dispatcher, Culture=neutral, PublicKeyToken=null'. The system cannot find the file specified.
SerializationBinder
. Writing your own binder that sanitizes deserialized types is also a good idea for security reasons as explained here. 2) Emit your own custom type property and parse it with a customJsonConverter
as shown, e.g., in Json.Net Serialization of Type with Polymorphic Child Object. – Scape