C#7.3下如何以多态方式反序列化API返回的JSON对象?
利用多态处理不同API查询结果的JSON反序列化
针对你遇到的四种查询结果共用相似JSON结构、仅Results节点类型不同的场景,可以通过抽象基类+多态+Json.NET自定义处理的方式避免重复代码,以下是具体实现方案:
一、定义抽象结果基类与具体实现类
先创建一个抽象基类作为所有结果类型的统一接口,再为四种查询结果分别定义对应的实体类:
// 抽象基类,统一所有结果类型的引用 public abstract class BaseResult { } // GetDatasetList对应的结果类 public class DatasetResult : BaseResult { public List<Dataset> Dataset { get; set; } } public class Dataset { public string Id { get; set; } public string Name { get; set; } // 根据API返回的JSON结构补充其他属性 } // GetParameterList对应的结果类 public class ParameterResult : BaseResult { public List<Parameter> Parameter { get; set; } } public class Parameter { public string ParamId { get; set; } public string DisplayName { get; set; } // 根据API返回的JSON结构补充其他属性 } // GetParameterValues对应的结果类 public class ParamValueResult : BaseResult { public List<ParamValue> ParamValue { get; set; } } public class ParamValue { public string Value { get; set; } public string Label { get; set; } // 根据API返回的JSON结构补充其他属性 } // GetData对应的结果类 public class DataResult : BaseResult { public List<DataPoint> Data { get; set; } } public class DataPoint { public DateTime Timestamp { get; set; } public decimal Value { get; set; } // 根据API返回的JSON结构补充其他属性 }
二、修改原有类以支持多态结果
借助Json.NET的JObject类型先接收Results节点,再通过类型判断转换为具体的BaseResult子类,或直接使用自定义转换器自动处理:
方案1:手动判断类型转换
修改_API类,增加类型转换方法:
using Newtonsoft.Json.Linq; public class QueryResults { public _API API { get; set; } public List<_RequestParam> RequestParams => API.Request.RequestParam; } public class _API { public _Request Request { get; set; } // 先反序列化为JObject,再转换为具体结果类型 public JObject Results { get; set; } // 获取强类型结果的方法 public BaseResult GetTypedResult() { if (Results.ContainsKey("Dataset")) return Results.ToObject<DatasetResult>(); if (Results.ContainsKey("Parameter")) return Results.ToObject<ParameterResult>(); if (Results.ContainsKey("ParamValue")) return Results.ToObject<ParamValueResult>(); if (Results.ContainsKey("Data")) return Results.ToObject<DataResult>(); throw new InvalidOperationException("无法识别的API结果类型"); } } public class _Request { public List<_RequestParam> RequestParam { get; set; } } public class _RequestParam { public string ParameterName { get; set; } public string ParameterValue { get; set; } }
方案2:自定义JsonConverter自动转换
如果希望直接反序列化为BaseResult类型,可自定义转换器:
public class BaseResultConverter : JsonConverter<BaseResult> { public override BaseResult ReadJson(JsonReader reader, Type objectType, BaseResult existingValue, bool hasExistingValue, JsonSerializer serializer) { JObject obj = JObject.Load(reader); if (obj.ContainsKey("Dataset")) return obj.ToObject<DatasetResult>(); if (obj.ContainsKey("Parameter")) return obj.ToObject<ParameterResult>(); if (obj.ContainsKey("ParamValue")) return obj.ToObject<ParamValueResult>(); if (obj.ContainsKey("Data")) return obj.ToObject<DataResult>(); throw new JsonSerializationException("无法识别的API结果类型"); } public override void WriteJson(JsonWriter writer, BaseResult value, JsonSerializer serializer) { serializer.Serialize(writer, value); } }
修改_API类的Results属性,指定转换器:
public class _API { public _Request Request { get; set; } [JsonConverter(typeof(BaseResultConverter))] public BaseResult Results { get; set; } }
三、反序列化与使用示例
无论哪种方案,最终都可以通过C# 7.3支持的类型模式匹配处理不同结果:
using Newtonsoft.Json; // 假设json是API返回的字符串 string json = GetApiResponse(); // 方案1的反序列化方式 var queryResults1 = JsonConvert.DeserializeObject<QueryResults>(json); BaseResult result1 = queryResults1.API.GetTypedResult(); // 方案2的反序列化方式 var queryResults2 = JsonConvert.DeserializeObject<QueryResults>(json); BaseResult result2 = queryResults2.API.Results; // 统一处理不同结果 switch (result1) { case DatasetResult datasetResult: foreach (var dataset in datasetResult.Dataset) { // 处理数据集逻辑 } break; case ParameterResult parameterResult: foreach (var param in parameterResult.Parameter) { // 处理参数逻辑 } break; case ParamValueResult paramValueResult: foreach (var value in paramValueResult.ParamValue) { // 处理参数值逻辑 } break; case DataResult dataResult: foreach (var point in dataResult.Data) { // 处理数据点逻辑 } break; default: throw new NotSupportedException("不支持的结果类型"); }
注意事项
- 确保实体类属性名称与JSON键完全匹配(若需忽略大小写,可在反序列化时配置
JsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver())。 - 需提前安装Newtonsoft.Json NuGet包(适用于C# 7.3对应的.NET Framework/.NET Core版本)。
内容的提问来源于stack exchange,提问作者David Hill
相关产品推荐
相关产品推荐

