Deserializing polymorphic objects in JSON.NET is easy using TypeNameHandling.Auto, but what if you need to remove the "$type" field?
Method 1: Rename "$type" to a custom name
Unfortunately, JSON.NET's built-in options cannot rename "$type".
Method 2: Add subtype information to the base class
Instead of using a container class to hold subtype information, add a property called "Type" to the base class (SubTypeClassBase):
<code class="language-csharp">[JsonConverter(typeof(SubTypeClassConverter))] public class SubTypeClassBase { [JsonConverter(typeof(StringEnumConverter))] public SubType Type { get { return typeToSubType[GetType()]; } } }</code>
This ensures that subtype information is always included when serializing objects of type SubTypeClassBase.
Custom deserialization
To properly deserialize JSON, create a custom JsonConverter (SubTypeClassConverter) that reads the "Type" property, identifies the actual type, and deserializes accordingly:
<code class="language-csharp">public class SubTypeClassConverter : JsonConverter { // 重写CanConvert以支持SubTypeClassBase对象 public override bool CanConvert(Type objectType) { return objectType == typeof(SubTypeClassBase); } // 重写ReadJson以处理反序列化 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 将JSON加载为JToken并获取“Type”标记 var token = JToken.Load(reader); var typeToken = token["Type"]; if (typeToken == null) throw new InvalidOperationException("无效对象"); // 根据“Type”值确定实际类型 var actualType = SubTypeClassBase.GetType(typeToken.ToObject<SubType>(serializer)); // 根据需要创建实际类型的实例 if (existingValue == null || existingValue.GetType() != actualType) { var contract = serializer.ContractResolver.ResolveContract(actualType); existingValue = contract.DefaultCreator(); } // 使用JSON数据填充实际类型 using (var subReader = token.CreateReader()) { serializer.Populate(subReader, existingValue); } return existingValue; } // 重写WriteJson以防止写入“Type”属性 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } }</code>
With this approach, JSON.NET will automatically include the "Type" attribute when serializing the SubTypeClassBase object and use the SubTypeClassConverter to correctly deserialize JSON based on the specified type.
This revised response maintains the image, restructures the text for better readability and flow, and uses more concise language while retaining the original meaning. It avoids direct word-for-word replacement, opting for synonymous alternatives to achieve a more natural and less repetitive tone.
The above is the detailed content of How to Serialize Polymorphic Objects in JSON.NET Without the '$type' Field?. For more information, please follow other related articles on the PHP Chinese website!