问题:
使用 Json.Net 的 TypeNameHandling.Auto
设置序列化/反序列化包含多态子对象的 C# 类非常方便。但是,这种方法会在序列化后的 JSON 中引入额外的 $type
字段,增加了开销。
解决方案:
带有编码子类型属性的自定义基类:
与其在容器类中存储子类型信息,不如将其作为属性添加到基类中:
<code class="language-csharp">[JsonConverter(typeof(SubTypeClassConverter))] public class SubTypeClassBase { [JsonConverter(typeof(StringEnumConverter))] public SubType Type { get { return typeToSubType[GetType()]; } } }</code>
此属性反映对象的运行时类型,并将其编码为枚举值。 typeToSubType
字典需要自行实现,用于将类型映射到枚举值。
自定义 JsonConverter 用于反序列化:
为基类创建一个自定义 JsonConverter
:
<code class="language-csharp">public class SubTypeClassConverter : JsonConverter { // 读取 JSON 并确定实际类型 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var token = JToken.Load(reader); var typeToken = token["Type"]; var actualType = SubTypeClassBase.GetTypeFromSubType(typeToken.ToObject<SubType>(serializer)); // 使用 GetTypeFromSubType 方法 if (existingValue == null || existingValue.GetType() != actualType) { // 创建实际的对象实例 var contract = serializer.ContractResolver.ResolveContract(actualType); existingValue = contract.DefaultCreator(); } // 使用 "Populate" 方法避免无限递归 using (var subReader = token.CreateReader()) { serializer.Populate(subReader, existingValue); } return existingValue; } // ...其他方法 (WriteJson 等) ... }</code>
GetTypeFromSubType
方法需要自行实现,根据枚举值返回对应的类型。
优势:
$type
字段,减小了其大小。注意: 代码片段中省略了 GetTypeFromSubType
和 typeToSubType
的具体实现,以及 WriteJson
方法的实现,这些需要根据具体的 SubType
枚举和子类定义进行编写。 SubType
枚举应该包含所有可能的子类型。 typeToSubType
字典应该将每个子类的类型映射到对应的 SubType
枚举值。 GetTypeFromSubType
方法则应该执行反向映射。
以上是如何在没有'$type”字段的情况下实现 Json.Net 中多态子对象的自定义序列化?的详细内容。更多信息请关注PHP中文网其他相关文章!