我一直在构建一个序列化系统,该系统可以根据对象装饰的属性分配一个特殊的ReferenceJConverter
或DefinitionJConverter
来工作。这些自定义JsonConverter
由自定义ContractResolver
中的逻辑分配,而不是采用更传统的技术来确定可以使用CanConvert
函数进行转换的内容。自定义解析器会覆盖CreateProperty
函数,如下所示:
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
JsonProperty property = base.CreateProperty(member, memberSerialization);
if (member is FieldInfo field)
{
// Does this field implement IList? This Utility function gets all member interfaces and checks if any of them equal the argued interface.
if (field.FieldType.ImplementsInterface<IList>())
{
// Are the elements of this IList decorated with [Ref]?
if (field.FieldType.GetGenericArguments()[0].HasAttribute<RefAttribute>())
{
// Does this collection field have [Def]?
if (field.HasAttribute<DefAttribute>())
{
// This is a collection of definitions.
property.Converter = new DefCollectionJConverter();
}
else
{
// This is a collection of references.
property.Converter = new RefCollectionJConverter();
}
}
}
else
{
// If the field's type class has been decorated with Ref.
if (field.FieldType.HasAttribute<RefAttribute>())
{
if (member.HasAttribute<DefAttribute>())
{
// If this particular field also has Def, it's a definition.
property.Converter = new DefinitionJConverter();
}
else
{
// Else it's a reference.
property.Converter = new ReferenceJConverter();
}
}
}
}
return property;
}
如您所见,它还可以处理集合,但我目前尚未对此进行测试。
这些自定义转换器要么按常规方式序列化对象(如果已定义),要么将其序列化为数字或清晰的字符串名(如果是引用)。
令人讨厌的是,序列化工作正常。我得到了想要的Json输出:
{
"wineofTheDayRef": "Merlot_WIN",
"wineOfTheDay": {
"tag": {
"literalTag": "Merlot_WIN"
},
},
}
反序列化会中断。 Json.NET似乎在CreateProperty
中循环并分配了所有正确的转换器,但是似乎从未调用过这些转换器。相反,我得到了:
Newtonsoft.Json.JsonSerializationException : Error converting value "Merlot_WIN" to type 'OrthrusStudios.Serialisation.PirateExample.Wine'. Path 'wineofTheDayRef', line 2, position 33.
----> System.ArgumentException:无法将System.String强制转换或转换为OrthrusStudios.Serialisation.Examples.Wine。
...警告我,参考字符串“ Merlot_WIN”无法转换为类型“ Wine”;我有一个自定义转换器,可以做到这一点,只需通过按其字符串名称查找反序列化的对象,或者如果尚未反序列化其定义,就向该对象发出请求。为什么我的代码甚至到达这里?
在我改用ContractResolver
方法之前,我的自定义转换器工作得很好。从理论上讲,逻辑不应该相同吗?
错误来自JsonSerializerInternalReader.EnsureType()
。