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

如何用C#派生类反序列化不同Web源的JSON数据?

解决JSON反序列化的抽象类继承优化方案

问题根源分析

栈溢出的核心原因是派生类中Value属性实现错误——未使用私有字段存储数据,而是在get/set逻辑中直接调用属性自身,触发无限递归。

正确的抽象类结构设计

抽象Data类及派生类

先实现支持字符串索引访问的抽象基类与具体数据类:

public abstract class Data
{
    // 定义字符串索引器的抽象接口
    public abstract object this[string key] { get; set; }
}

// 对应第一个数据源的具体数据类
public class Type1Data : Data
{
    public string Campo1 { get; set; }
    public decimal Valor { get; set; }

    // 实现索引器,映射到具体字段
    public override object this[string key]
    {
        get => key switch
        {
            nameof(Campo1) => Campo1,
            nameof(Valor) => Valor,
            _ => throw new KeyNotFoundException($"Key {key} not found in Type1Data")
        };
        set
        {
            switch (key)
            {
                case nameof(Campo1):
                    Campo1 = value as string;
                    break;
                case nameof(Valor):
                    Valor = Convert.ToDecimal(value);
                    break;
                default:
                    throw new KeyNotFoundException($"Key {key} not found in Type1Data");
            }
        }
    }
}

// 对应第二个数据源的具体数据类
public class Type2Data : Data
{
    public string IndiceNome { get; set; }
    public double Pontuacao { get; set; }

    // 实现索引器,映射到具体字段
    public override object this[string key]
    {
        get => key switch
        {
            nameof(IndiceNome) => IndiceNome,
            nameof(Pontuacao) => Pontuacao,
            _ => throw new KeyNotFoundException($"Key {key} not found in Type2Data")
        };
        set
        {
            switch (key)
            {
                case nameof(IndiceNome):
                    IndiceNome = value as string;
                    break;
                case nameof(Pontuacao):
                    Pontuacao = Convert.ToDouble(value);
                    break;
                default:
                    throw new KeyNotFoundException($"Key {key} not found in Type2Data");
            }
        }
    }
}

抽象Root类及派生类(修复栈溢出)

通过私有字段存储数据,同时为反序列化提供具体类型绑定的属性:

using System.Text.Json.Serialization;

public abstract class Root
{
    [JsonPropertyName("@odata.context")]
    public string ODataContext { get; set; }
    public abstract List<Data> Value { get; set; }
}

// 泛型抽象基类,消除重复代码
public abstract class Root<T> : Root where T : Data
{
    [JsonPropertyName("value")]
    public List<T> TypedValue { get; set; }

    public override List<Data> Value
    {
        get => TypedValue?.Cast<Data>().ToList() ?? new List<Data>();
        set => TypedValue = value?.Cast<T>().ToList() ?? new List<T>();
    }
}

// 各数据源的Root类只需继承泛型基类,无需重复实现逻辑
public class RootType1 : Root<Type1Data> { }
public class RootType2 : Root<Type2Data> { }

反序列化示例(使用System.Text.Json)

// 模拟从Type1数据源获取的JSON
string type1Json = @"
{
    ""@odata.context"": ""https://example.com/odata/$metadata#Cambios"",
    ""value"": [
        { ""Campo1"": ""USD"", ""Valor"": 5.25 },
        { ""Campo1"": ""EUR"", ""Valor"": 5.6 }
    ]
}";

// 反序列化为具体Root类
RootType1 root1 = JsonSerializer.Deserialize<RootType1>(type1Json);

// 通过抽象Root类统一访问数据
foreach (Data item in root1.Value)
{
    Console.WriteLine($"Moeda: {item["Campo1"]}, Cotação: {item["Valor"]}");
}

// 模拟从Type2数据源获取的JSON
string type2Json = @"
{
    ""@odata.context"": ""https://example.com/odata/$metadata#Indices"",
    ""value"": [
        { ""IndiceNome"": ""IBOV"", ""Pontuacao"": 125000.5 },
        { ""IndiceNome"": ""S&P500"", ""Pontuacao"": 4500.2 }
    ]
}";

RootType2 root2 = JsonSerializer.Deserialize<RootType2>(type2Json);
foreach (Data item in root2.Value)
{
    Console.WriteLine($"Índice: {item["IndiceNome"]}, Pontuação: {item["Pontuacao"]}");
}

错误代码对比(栈溢出原因)

如果之前的派生类是如下写法,会触发无限递归导致栈溢出:

// 错误示例,禁止使用
public class RootType1 : Root
{
    public override List<Data> Value
    {
        get => Value; // 递归调用自身,无限循环
        set => Value = value;
    }
}

必须通过私有字段或泛型属性存储实际数据,避免直接访问属性本身。

内容的提问来源于stack exchange,提问作者Antônio Pragana

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 04:30:01