我有一个抽象基类:
[JsonConverter(typeof(Converter))]
public abstract class TextComponent {
...
public bool Bold { get; set; }
public TextComponent[] Extra { get; set; }
...
}
以及从中继承的更多类。其中一个是StringComponent
:
public sealed class StringComponent : TextComponent
{
public string Text { get; set; }
public StringComponent(string text)
{
Text = text;
}
}
Converter
,是应用于TextComponent
的JsonConverter
,看起来像这样:
private sealed class Converter : JsonConverter
{
....
public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
JsonSerializer serializer)
{
var tok = JToken.Load(reader);
switch (tok)
{
...
case JObject x:
var dic = (IDictionary<string, JToken>) x;
if (dic.ContainsKey("text")) return x.ToObject<StringComponent>();
...
...
}
}
...
public override bool CanConvert(Type objectType) => objectType == typeof(TextComponent);
}
问题:
var str = "{"text":"hello world"}";
var obj = JsonConvert.DeserializeObject<TextComponent>(str);
// this doesn't work either:
var obj = JsonConvert.DeserializeObject<StringComponent>(str);
这最终进入了一个无限的"循环",最终导致了StackOverflow
,因为在调用DeserializeObject<Stringcomponent>
或ToObject<StringComponent>
时,使用了基类的JsonConverter
(Converter
),再次使用这些方法。这不是所需的行为。当序列化类序列化类时,它们不应使用基类的JsonConverter
。如果您查看Converter
的CanConvert
方法,我也只允许TextComponent
允许它,而不适合任何一个派生类。
那么我该如何解决?
您可以将子类合同上的转换器设置为null;
public override bool CanWrite => false;
public override bool CanRead => true;
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
if (objectType == typeof(BaseClass))
{
JObject item = JObject.Load(reader);
if (item["isClass2"].Value<bool>())
{
return item.ToObject<ChildClass2>(serializer);
}
else
{
return item.ToObject<ChildClass1>(serializer);
}
}
else
{
serializer.ContractResolver.ResolveContract(objectType).Converter = null;
return serializer.Deserialize(reader, objectType);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
您是否尝试从基类中删除[JSONCONVERT] -ATRIBUTE?在我的示例中,我手动调用"自定义"转换器: