使用JsonConverterAttribute时,自定义inheritanceJsonConverter失败

我试图反序列化派生类型,我想使用自定义属性Type来区分派生类型。

 [ { "Type": "a", "Height": 100 }, { "Type": "b", "Name": "Joe" } ] 

我找到的解决方案是创建一个自定义的JsonConverter 。 在ReadJson我读取了Type属性,并通过ToObject函数实例化该类型。 一切正常,直到我使用JsonConverterAttributeReadJson方法无限循环,因为该属性也应用于子类型。

如何防止将此属性应用于子类型?

 [JsonConverter(typeof(TypeSerializer))] public abstract class Base { private readonly string type; public Base(string type) { this.type = type; } public string Type { get { return type; } } } public class AType : Base { private readonly int height; public AType(int height) : base("a") { this.height = height; } public int Height { get { return height; } } } public class BType : Base { private readonly string name; public BType(string name) : base("b") { this.name = name; } public string Name { get { return name; } } } public class TypeSerializer : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(Base); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { serializer.Serialize(writer, value); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var j = JObject.Load(reader); var type = j["Type"].ToObject(); if (type == "a") // Infinite Loop! StackOverflowException return j.ToObject(); if (type == "b") return j.ToObject(); throw new NotImplementedException(type); } } [TestFixture] public class InheritanceSerializeTests { [Test] public void Deserialize() { var json = @"{""Type"":""a"", ""Height"":100}"; JObject.Parse(json).ToObject(); // Crash } } 

我目前正在处理的项目有一个非常类似的问题:我想制作一个自定义的JsonConverter并通过属性将它映射到我的实体,但随后代码被困在一个无限循环中。

在我的情况下,诀窍是使用serializer.Populate而不是JObject.ToObject (我不能使用.ToObject即使我想;我使用的是版本3.5.8,其中此函数不存在)。 下面以我的ReadJson方法为例:

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JContainer lJContainer = default(JContainer); if (reader.TokenType == JsonToken.StartObject) { lJContainer = JObject.Load(reader); existingValue = Convert.ChangeType(existingValue, objectType); existingValue = Activator.CreateInstance(objectType); serializer.Populate(lJContainer.CreateReader(), existingValue); } return existingValue; } 

Base类中删除[JsonConverter(typeof(TypeSerializer))]属性,并在Deserialize测试中替换以下行:

 JObject.Parse(json).ToObject(); // Crash 

与这一个:

 var obj = JsonConvert.DeserializeObject(json, new TypeSerializer()); 

更新1此更新与问题提问者的评论相符:

[JsonConverter(typeof(TypeSerializer))]属性保留给Base类。 使用以下行进行反序列化:

 var obj = JsonConvert.DeserializeObject(json); 

并修改ReadJson方法,如下所示:

 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var j = JObject.Load(reader); if (j["Type"].ToString() == "a") return new AType(int.Parse(j["Height"].ToString())); return new BType(j["Name"].ToString()); }