使用对象支持字段反序列化通用子类
De-Serializing generic sublass with object backing field
不确定如何正确地为这个问题命名,但这就是问题所在。
public sealed class ObjectPropertySubclassTest
{
private sealed class CleverBaseClassConverter : JsonConverter<BaseClass>
{
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, BaseClass value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override BaseClass ReadJson(JsonReader reader, Type objectType, BaseClass existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token["Components"] is JArray)
{
var collection=new CollectionClass();
serializer.Populate(token.CreateReader(), collection);
return collection;
}
else
{
if (token["Value"] is JArray)
{
var obj = new SubClass<IEnumerable<BaseClass>>();
serializer.Populate(token.CreateReader(), obj);
return obj;
}
else
{
var obj = new SubClass<object>();
serializer.Populate(token.CreateReader(), obj);
return obj;
}
}
}
}
[JsonConverter(typeof(CleverBaseClassConverter))]
private abstract class BaseClass
{
public object Value { get; set; }
}
private class SubClass<T>: BaseClass
{
public new T Value
{
get => (T) base.Value;
set => base.Value = value;
}
}
private sealed class CollectionClass : SubClass<IEnumerable<BaseClass>>
{
public IEnumerable<BaseClass> Components { get=>Value; set=>Value=value; }
public bool ShouldSerializeValue() => false;
}
[Test]
public void Test()
{
var item=new CollectionClass
{
Components=new BaseClass[] {new SubClass<string>{Value="hi"},new SubClass<int>{Value=5}, }
};
var json = JsonConvert.SerializeObject(item);
var copy = JsonConvert.DeserializeObject<CollectionClass>(json);
//why does copy.components have 4 items (2 doubling up)?
//why does copy.value have 4 items (2 doubling up) as well?
}
}
Serializaiton 按预期工作,但是当我将 json 反序列化为集合 class 时,它最终有 4 个项目而不是 2 个(在组件中)。我在反序列化方面做了一些根本性的错误吗?
还有为什么它仍然序列化 "Value" 以收集 class
JSON:(我有 json 转换器反序列化正确的子 class)
{"Components":[{"Value":"hi"},{"Value":5}],"Value":[{"Value":"hi"},{"Value":5}]}
使用
TypeNameHandling.Auto
而不是
TypeNameHandling.Object
我想出了如何让它工作以及为什么它会重复项目
private class SubClass<T>: BaseClass
{
public new T Value
{
get => (T) base.Value;
set => base.Value = value;
}
//Added this here in the generic subclass
public virtual bool ShouldSerializeValue() => true;
}
然后在集合subsclass
private sealed class CollectionClass : SubClass<IEnumerable<BaseClass>>
{
public IEnumerable<BaseClass> Components { get=>Value; set=>Value=value; }
//this prevents value to be serialized for this type of class
public override bool ShouldSerializeValue() => false;
}
最后为什么要复制它?
因为值是序列化的,并且它在反序列化值部分之后聚合 "components",所以在反序列化值之后,它将反序列化以已经反序列化的值列表为基础的组件,并将组件添加到该集合中。因此在收集 class 的情况下停止值序列化它不会有 "values" 的基础 json 因此不会复制它。
不确定如何正确地为这个问题命名,但这就是问题所在。
public sealed class ObjectPropertySubclassTest
{
private sealed class CleverBaseClassConverter : JsonConverter<BaseClass>
{
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, BaseClass value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override BaseClass ReadJson(JsonReader reader, Type objectType, BaseClass existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token["Components"] is JArray)
{
var collection=new CollectionClass();
serializer.Populate(token.CreateReader(), collection);
return collection;
}
else
{
if (token["Value"] is JArray)
{
var obj = new SubClass<IEnumerable<BaseClass>>();
serializer.Populate(token.CreateReader(), obj);
return obj;
}
else
{
var obj = new SubClass<object>();
serializer.Populate(token.CreateReader(), obj);
return obj;
}
}
}
}
[JsonConverter(typeof(CleverBaseClassConverter))]
private abstract class BaseClass
{
public object Value { get; set; }
}
private class SubClass<T>: BaseClass
{
public new T Value
{
get => (T) base.Value;
set => base.Value = value;
}
}
private sealed class CollectionClass : SubClass<IEnumerable<BaseClass>>
{
public IEnumerable<BaseClass> Components { get=>Value; set=>Value=value; }
public bool ShouldSerializeValue() => false;
}
[Test]
public void Test()
{
var item=new CollectionClass
{
Components=new BaseClass[] {new SubClass<string>{Value="hi"},new SubClass<int>{Value=5}, }
};
var json = JsonConvert.SerializeObject(item);
var copy = JsonConvert.DeserializeObject<CollectionClass>(json);
//why does copy.components have 4 items (2 doubling up)?
//why does copy.value have 4 items (2 doubling up) as well?
}
}
Serializaiton 按预期工作,但是当我将 json 反序列化为集合 class 时,它最终有 4 个项目而不是 2 个(在组件中)。我在反序列化方面做了一些根本性的错误吗? 还有为什么它仍然序列化 "Value" 以收集 class
JSON:(我有 json 转换器反序列化正确的子 class)
{"Components":[{"Value":"hi"},{"Value":5}],"Value":[{"Value":"hi"},{"Value":5}]}
使用
TypeNameHandling.Auto
而不是
TypeNameHandling.Object
我想出了如何让它工作以及为什么它会重复项目
private class SubClass<T>: BaseClass
{
public new T Value
{
get => (T) base.Value;
set => base.Value = value;
}
//Added this here in the generic subclass
public virtual bool ShouldSerializeValue() => true;
}
然后在集合subsclass
private sealed class CollectionClass : SubClass<IEnumerable<BaseClass>>
{
public IEnumerable<BaseClass> Components { get=>Value; set=>Value=value; }
//this prevents value to be serialized for this type of class
public override bool ShouldSerializeValue() => false;
}
最后为什么要复制它? 因为值是序列化的,并且它在反序列化值部分之后聚合 "components",所以在反序列化值之后,它将反序列化以已经反序列化的值列表为基础的组件,并将组件添加到该集合中。因此在收集 class 的情况下停止值序列化它不会有 "values" 的基础 json 因此不会复制它。