問題:
使用 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中文網其他相關文章!