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

C#:将含未知键的JSON对象数组反序列化为泛型属性

解决Newtonsoft.Json反序列化动态键对象为泛型列表的问题

你遇到的核心痛点很明确:API返回的Settings是个带动态自定义键的对象,但你不想为100+个可能的键提前定义模型字段,而是希望转换成ColumnName+ColumnValue的泛型列表。下面给你两种实用的解决方案:


方案一:手动遍历JObject属性(快速落地)

既然你已经在用dynamic和JObject处理反序列化,最直接的方式就是手动遍历Settings的键值对,逐个生成ColumnSettingsResult实例:

修改你现有foreach循环里的代码:

foreach (var obj in innerResult)
{
    resultList.Add(
        new EnumerateAccountHistoryStatisticsResult
        {
            AccountId = obj.AccountId,
            Flags = obj.Flags.ToObject<IEnumerable<string>>(),
            PartnerId = obj.PartnerId,
            // 把Settings对象转成目标列表
            Settings = obj.Settings.Cast<JProperty>()
                .Select(prop => new ColumnSettingsResult
                {
                    ColumnName = prop.Name,
                    ColumnValue = prop.Value.ToString()
                })
                .ToList()
        });
}

这种方式不需要改模型结构,也不用额外写转换器,适合快速调整现有代码逻辑。


方案二:自定义JsonConverter(优雅长期方案)

如果想让模型自动处理这种转换,避免每次手动遍历,可以写一个自定义的JSON转换器:

1. 实现转换器类

public class SettingsConverter : JsonConverter<List<ColumnSettingsResult>>
{
    public override List<ColumnSettingsResult> ReadJson(JsonReader reader, Type objectType, List<ColumnSettingsResult> existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 读取JSON里的Settings对象
        var settingsObj = JObject.Load(reader);
        // 把每个键值对转成ColumnSettingsResult
        return settingsObj.Properties()
            .Select(prop => new ColumnSettingsResult
            {
                ColumnName = prop.Name,
                ColumnValue = prop.Value.ToString()
            })
            .ToList();
    }

    public override void WriteJson(JsonWriter writer, List<ColumnSettingsResult> value, JsonSerializer serializer)
    {
        // 如果需要把列表序列化回原JSON格式,这里做反向转换
        var settingsObj = new JObject();
        foreach (var setting in value)
        {
            settingsObj.Add(setting.ColumnName, setting.ColumnValue);
        }
        settingsObj.WriteTo(writer);
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<ColumnSettingsResult>);
    }
}

2. 在模型中绑定转换器

修改你的主模型,给Settings属性加上转换器特性:

public class EnumerateAccountHistoryStatisticsResult
{
    public int AccountId { get; set; }
    public IEnumerable<string> Flags { get; set; }
    public int PartnerId { get; set; }
    
    [JsonConverter(typeof(SettingsConverter))]
    public List<ColumnSettingsResult> Settings { get; set; }
}

3. 简化反序列化代码

现在你可以直接用ToObject自动完成转换,不用再手动处理:

foreach (var obj in innerResult)
{
    resultList.Add(obj.ToObject<EnumerateAccountHistoryStatisticsResult>());
}

特殊情况适配:如果Settings是数组类型

如果你说的“Settings数组”是指每个元素是单个键值对的对象(比如[{"AR":"val1"}, {"AN":"val2"}]),只需要稍微调整转换逻辑:

// 手动转换方式
Settings = obj.Settings.Cast<JObject>()
    .Select(jObj => 
    {
        var prop = jObj.Properties().First();
        return new ColumnSettingsResult
        {
            ColumnName = prop.Name,
            ColumnValue = prop.Value.ToString()
        };
    })
    .ToList()

对应的自定义转换器也可以调整ReadJson方法来适配这种数组结构。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 09:05:10