5

I have some objects:

public class MyObject
{
    public MyField Field { get; set; }
}

public class MyField
{
    [JsonProperty]
    public Entity MyEntity { get; set; }
    public IEntity IMyEntity { get; set; }
}

public interface IEntity
{
    string MyStr { get; }
}

public class Entity : IEntity
{
}

Then I am trying to do something like

JsonConvert.DeserializeObject<MyObject>(myObjStr); 

Which throws an error similar to

Could not create an instance of type MyObject... Type is an interface or abstract class and cannot be instantiated. Path 'MyField.IMyEntity.MyInt'

I can't change the field or entity, as that is in another group's codebase. The MyObject class is in mine. Is there a way to deserialize this object? I've tried a few things with JsonSerializerSettings here JSON.NET - how to deserialize collection of interface-instances? but to no avail.

Community
  • 1
  • 1
justindao
  • 2,273
  • 4
  • 18
  • 34

1 Answers1

3

You can create your own JSON converter which allows you to specify type mapping:

public class JsonTypeMapper<TFromType, TToType> : JsonConverter
{
    public override bool CanConvert(Type objectType) => objectType == typeof(TFromType);

    public override object ReadJson(JsonReader reader,
     Type objectType, object existingValue, JsonSerializer serializer)
    {
        return serializer.Deserialize<TToType>(reader);
    }

    public override void WriteJson(JsonWriter writer,
        object value, JsonSerializer serializer)
    {
        serializer.Serialize(writer, value);
    }
}

Then you deserialize like this:

JsonConvert.DeserializeObject<MyObject>(myObjStr, new JsonSerializerSettings
{
    Converters = new List<JsonConverter> { new JsonTypeMapper<IEntity, Entity>() }
                                                            //^^^^^^^, ^^^^^^
}); 
Rob
  • 26,989
  • 16
  • 82
  • 98
  • 1
    To make the write even simpler, you could override [`CanWrite`](http://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_JsonConverter_CanWrite.htm) and return `false`. – dbc Jun 17 '16 at 00:20
  • @dbc Correct! Though `WriteJson` is actually an abstract method, so we'd have to replace the implementation with throwing a `NotImplementedException` (or similar). If `JsonTypeMapper` itself were intended to be overridden (or abstract), I'd definitely stick with `CanWrite`, but as a matter of preference, I try to avoid `NotImplementedException`. – Rob Jun 17 '16 at 00:32