【发布时间】:2018-03-14 16:38:28
【问题描述】:
我们在序列化程序设置中使用TypeNameHandling = TypeNameHandling.Objects 将Web API 与Json.Net 一起使用。这很好用,但我们只在客户端使用类型信息,从不用于反序列化。我们的序列化对象如下所示:
{
"$type": "PROJECTNAME.Api.Models.Directory.DtoName, PROJECTNAME.Api",
"id": 67,
"offices": [{
"$type": "PROJECTNAME.Api.Models.Directory.AnotherDtoName, PROJECTNAME.Api",
"officeName": "FOO"
}]
},
我想自定义 $type 属性中的值,使其显示为:
{
"$type": "Models.Directory.DtoName",
"id": 67,
"offices": [{
"$type": "Models.Directory.AnotherDtoName",
"officeName": "FOO"
}]
},
我已经有一个继承自 CamelCasePropertyNamesContractResolver 的合约解析器。我想我需要做的是关闭TypeNameHandling 并自己添加一个自定义属性。我有 95% 在那里:
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var assemblyName = type.Assembly.GetName().Name;
var typeName = type.FullName.Substring(assemblyName.Length + 1);
var typeProperty = new JsonProperty()
{
PropertyName = "$type",
PropertyType = typeof(string),
Readable = true,
Writable = true,
ValueProvider = null // ????? typeName
};
var retval = base.CreateProperties(type, memberSerialization);
retval.Add(typeProperty);
return retval;
}
在这一点上,我坚持提供财产的价值。
我不确定这是不是正确的方法,因为来自 Json.Net 的每个 ValueProvider 类型都将 MemberInfo 作为构造函数参数。我没有MemberInfo 作为参数提供,所以....我被卡住了。
如何添加自定义 $type 值?由于我没有在 C# 中进行反序列化,因此我永远不需要将类型信息转换回类型。
【问题讨论】:
-
不要添加
$type属性。而是创建一个customISerializationBinder,例如JSON.Net: deserializing polymorphic types without specifying the assembly、Using a custom type discriminator to tell JSON.net which type of a class hierarchy to deserialize 和Newtonsoft.json serializing and deserializing base/inheirited where classes are from shared projects 中的@。 -
我没有在 C# 中进行反序列化。
-
ISerializationBinder.BindToName在多态类型的序列化过程中被调用,以指定要为$type发出的类型信息,所以应该做你想做的事情。 -
啊啊啊啊。我正要问我是否误解了
ISerializationBinder的目的。我会检查一下。 -
请注意,文档有点过时了,因为最近 Newtonsoft 不得不用自己的
ISerializationBinder替换某些 .Net 核心版本中显然缺少的SerializationBinder。如果您使用的是 Json.NET 10.0 或更高版本,请使用 `ISerializationBinder`。