如何用Newtonsoft.Json反序列化含不同类型元素的JSON数组
这个多态反序列化的问题我之前做过滤逻辑的时候经常碰到,Newtonsoft.Json其实有很成熟的解决办法,咱们一步步来搞定它:
解决方案核心思路
利用基类+派生类的结构兼容group和condition两种类型,再配合自定义JsonConverter,根据JSON里的type字段自动判断要反序列化的目标类。
1. 补全类结构定义
先创建一个抽象基类,让Group和Condition都继承它,这样就能统一放在conditions数组里:
// 抽象基类,统一两种过滤类型 public abstract class FilterBase { [JsonProperty("type")] public abstract string Type { get; } } // Condition类型的具体实现 public class Condition : FilterBase { public override string Type => "condition"; [JsonProperty("metric")] public string Metric { get; set; } [JsonProperty("operator")] public string Operator { get; set; } [JsonProperty("value")] public string Value { get; set; } } // 补全你未写完的Group类 public class Group : FilterBase { public override string Type => "group"; [JsonProperty("logicalOperator")] public string LogicalOperator { get; set; } [JsonProperty("conditions")] public List<FilterBase> Conditions { get; set; } }
2. 实现自定义JsonConverter
这个转换器的作用是读取JSON里的type字段,决定把当前节点反序列化成Group还是Condition:
public class FilterConverter : JsonConverter { public override bool CanConvert(Type objectType) { // 只处理FilterBase及其派生类 return typeof(FilterBase).IsAssignableFrom(objectType); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jObject = JObject.Load(reader); var filterType = jObject["type"].Value<string>(); // 根据type字段匹配对应的类 switch (filterType) { case "group": return jObject.ToObject<Group>(serializer); case "condition": return jObject.ToObject<Condition>(serializer); default: throw new JsonSerializationException($"未知的过滤类型: {filterType}"); } } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 序列化时直接用默认逻辑即可 serializer.Serialize(writer, value); } }
3. 执行反序列化操作
最后只需要在反序列化时指定咱们写的转换器,就能完美处理混合类型的数组了:
// 你的原始JSON字符串 var json = @"{ ""type"": ""group"", ""logicalOperator"": ""or"", ""conditions"":[{ ""type"": ""condition"", ""metric"": ""CTR"", ""operator"": "">="", ""value"": ""123"" }, { ""type"": ""group"", ""logicalOperator"": ""and"", ""conditions"": [{ ""type"": ""condition"", ""metric"": ""CTR"", ""operator"": "">="", ""value"": ""123"" }] } ] }"; // 配置序列化设置,添加自定义转换器 var settings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new FilterConverter() } }; // 反序列化为Group类型(因为你的根节点是group) var filterGroup = JsonConvert.DeserializeObject<Group>(json, settings);
后续如果需要新增其他过滤类型,只需要新增一个继承FilterBase的类,再在转换器的switch里加个case就行,扩展性很强。
内容的提问来源于stack exchange,提问作者Максим Устелемов
相关产品推荐
相关产品推荐

