Json.Net:在填充接口属性时指定对象类型

时间:2018-09-21 19:50:29

标签: json json.net

我有一个对象,该对象实现的接口的属性是另一个接口:

File "C:/Users/PycharmProjects/CleverBotBot.py", line 2, in <module>
from .chrome.webdriver import WebDriver as Chrome  # noqa
ModuleNotFoundError: No module named 'selenium.webdriver.chrome

我可以创建Master类的实例,然后使用public interface IMaster { ISlave ObjectProp {get; set; } } public interface ISlave { string Name {get; set; } } ... public class Master : IMaster { public ISlave ObjectProp {get; set; } } public class Slave : ISlave { public string Name {get; set; } } 对其进行反序列化。
但是,在反序列化属性时,解析器显然无法创建接口的实例。

是否有一种方法(通过属性,回调等)告诉Json库创建Slave类的实例(实现所讨论的接口)?

1 个答案:

答案 0 :(得分:1)

是的,这看起来像是重复的-JsonConverterAttribute似乎可以正常工作。为了完整起见,下面是解决方案:

...
public class Master : IMaster
{
   [JsonConverter(typeof(ModelJsonConverter), typeof(Slave))]
   public ISlave ObjectProp {get; set; }
}
...
public class ModelJsonConverter : JsonConverter
    {
        public Type InstanceType { get; set; }
        public ModelJsonConverter(Type instanceType):base()
        {
            InstanceType = instanceType;
        }

        public override bool CanWrite => false;
        public override bool CanRead => true;
        public override bool CanConvert(Type objectType)
        {
            if (objectType == InstanceType) return true;
            else return InstanceType.GetTypeInfo().Is​Subclass​Of(objectType);
        }

        public override void WriteJson(JsonWriter writer,
                                       object value, JsonSerializer serializer)
        {
            throw new InvalidOperationException("Use default serialization.");
        }

        public override object ReadJson(JsonReader reader,
                                        Type objectType, object existingValue,
                                        JsonSerializer serializer)
        {
            if (reader.TokenType == JsonToken.Null) return null;
            else if (reader.TokenType != JsonToken.StartObject) throw new JsonException($"Unexpected Json token at {reader.Path}: {reader.TokenType.ToString()}");
            var deserialized = Activator.CreateInstance(InstanceType);
            serializer.Populate(reader, deserialized);
            return deserialized;
        }

    }