You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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("不支持的结果类型");
}

注意事项

  1. 确保实体类属性名称与JSON键完全匹配(若需忽略大小写,可在反序列化时配置JsonSerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver())。
  2. 需提前安装Newtonsoft.Json NuGet包(适用于C# 7.3对应的.NET Framework/.NET Core版本)。

内容的提问来源于stack exchange,提问作者David Hill

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 21:13:36