如何使用自定义JsonConverter反序列化组合模式的复合列表对象
实现思路
- 区分节点类型:反序列化时首先判断当前JToken类型,若JObject仅包含1个键且对应值为JArray,则该节点为Composite节点,键名即为Composite的name属性;若JObject包含
experience、name等叶子节点专属字段,则为Leaf节点。 - 递归处理子节点:Composite的子节点数组可通过递归逻辑逐个解析,子节点可能是Composite也可能是Leaf,按上述规则判断后递归解析即可。
完整实现代码
你可以直接在现有CompositeConverter类中补充ReadJson实现即可:
public class CompositeConverter : JsonConverter { // 原有序列化逻辑可以优化,不需要反射直接访问属性 public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { Composite composite = (Composite)value; JArray array = new JArray(); foreach (Component e in composite._children) { array.Add(JToken.FromObject(e, serializer)); } JObject obj = new JObject(); obj.Add(composite.name, array); obj.WriteTo(writer); } // 新增反序列化逻辑 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JObject jObj = JObject.Load(reader); // Composite节点仅会有一个属性,属性名为name,值为子节点数组 var compositeProp = jObj.Properties().First(); string compositeName = compositeProp.Name; JArray childrenArray = (JArray)compositeProp.Value; Composite composite = new Composite(compositeName); foreach (var childToken in childrenArray) { Component childComponent; var childJObj = (JObject)childToken; // 判断是否为Leaf节点:存在experience字段即为Leaf if (childJObj.ContainsKey("experience")) { childComponent = childJObj.ToObject<Leaf>(serializer); } else { // 递归反序列化Composite节点 childComponent = childJObj.ToObject<Composite>(serializer); } composite.Add(childComponent); } return composite; } public override bool CanConvert(Type objectType) { return typeof(Composite).IsAssignableFrom(objectType); } }
调用示例
// 传入你序列化得到的JSON字符串即可直接反序列化 Composite root = JsonConvert.DeserializeObject<Composite>(yourJsonString);
注意事项
- 若后续Leaf节点扩展字段,判断Leaf的逻辑可以按需调整,比如改为判断节点没有数组类型的属性即可。
- 现有逻辑完全适配你当前的序列化输出结构,不需要修改原有类定义和序列化逻辑。
内容的提问来源于stack exchange,提问作者Povilas Dirse
相关产品推荐
相关产品推荐

