问题描述
我正在尝试反序列化派生类型,并且我想使用自定义属性Type
来区分派生类型.
I am trying to deserialize derived type, and I want to use a custom property Type
to distinguish between derived types.
[
{
"Type": "a",
"Height": 100
},
{
"Type": "b",
"Name": "Joe"
}
]
我遇到的解决方案是创建一个自定义JsonConverter
.在ReadJson
上,我读取Type
属性,并通过ToObject<T>
函数实例化该类型.一切正常,直到使用JsonConverterAttribute
. ReadJson
方法无限循环,因为该属性也适用于子类型.
The solution I came to was to create a custom JsonConverter
. On ReadJson
I read the Type
property and instantiate that type through the ToObject<T>
function. Everything works fine until I use a JsonConverterAttribute
. The ReadJson
method loops infinitely because the attribute is applied on subtypes too.
如何防止将此属性应用于子类型?
How do I prevent this attribute from being applied to the subtypes?
[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<string>();
if (type == "a")
// Infinite Loop! StackOverflowException
return j.ToObject<AType>();
if (type == "b")
return j.ToObject<BType>();
throw new NotImplementedException(type);
}
}
[TestFixture]
public class InheritanceSerializeTests
{
[Test]
public void Deserialize()
{
var json = @"{""Type"":""a"", ""Height"":100}";
JObject.Parse(json).ToObject<Base>(); // Crash
}
}
推荐答案
我目前正在处理的项目有一个非常相似的问题:我想制作一个自定义JsonConverter
并通过属性将其映射到我的实体,但随后代码陷入了无限循环.
I had a very similar problem with a project that I am currently working on: I wanted to make a custom JsonConverter
and map it to my entities via attributes, but then the code got trapped in an infinite loop.
在我的情况下,技巧是使用serializer.Populate
而不是JObject.ToObject
(即使我愿意也不能使用.ToObject
;我使用的是3.5.8版,其中该功能不存在).下面是我的ReadJson
方法作为示例:
What did the trick in my case was using serializer.Populate
instead of JObject.ToObject
(I couldn't use .ToObject
even if I wanted to; I am using version 3.5.8, in which this function does not exist). Below is my ReadJson
method as an example:
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;
}
这篇关于使用JsonConverterAttribute时,自定义继承JsonConverter失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!