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

C#使用Newtonsoft Json反序列化含指定前缀动态键的JSON对象

方案1:使用[JsonExtensionData]原生特性(推荐,实现成本最低)

Newtonsoft.Json自带的[JsonExtensionData]特性可以自动把所有未在实体类中显式定义的键值对存入指定字典,你只需要后续对字典内容按前缀分组即可。

实体类定义:

public class LocalizedItem
{
    // 固定字段显式定义
    [JsonProperty("id")]
    public string Id { get; set; }

    // 存放所有未匹配的动态字段
    [JsonExtensionData]
    private Dictionary<string, JToken> _dynamicFields;

    // 按前缀分组后的属性,懒加载避免重复计算
    private Dictionary<string, List<string>> _descriptions;
    public Dictionary<string, List<string>> Descriptions
    {
        get
        {
            if (_descriptions == null)
            {
                _descriptions = _dynamicFields
                    .Where(kv => kv.Key.StartsWith("descriptions_"))
                    .ToDictionary(
                        kv => kv.Key["descriptions_".Length..], // 截取后缀作为语言标识
                        kv => kv.Value.ToObject<List<string>>()
                    );
            }
            return _descriptions;
        }
    }

    private Dictionary<string, string> _officialTitles;
    public Dictionary<string, string> OfficialTitles
    {
        get
        {
            if (_officialTitles == null)
            {
                _officialTitles = _dynamicFields
                    .Where(kv => kv.Key.StartsWith("official_title_"))
                    .ToDictionary(
                        kv => kv.Key["official_title_".Length..],
                        kv => kv.Value.ToObject<string>()
                    );
            }
            return _officialTitles;
        }
    }

    private Dictionary<string, string> _authTowns;
    public Dictionary<string, string> AuthTowns
    {
        get
        {
            if (_authTowns == null)
            {
                _authTowns = _dynamicFields
                    .Where(kv => kv.Key.StartsWith("auth_town_"))
                    .ToDictionary(
                        kv => kv.Key["auth_town_".Length..],
                        kv => kv.Value.ToObject<string>()
                    );
            }
            return _authTowns;
        }
    }
}

使用方式:

直接按常规方式反序列化即可,无需额外配置:

var result = JsonConvert.DeserializeObject<LocalizedItem>(yourJsonString);
// 取值示例:获取bg语言的官方标题
var bgTitle = result.OfficialTitles["bg"];

方案2:自定义JsonConverter(适合需要序列化回原结构、或有更多解析自定义需求的场景)

如果需要完全控制解析逻辑,或者需要把实体序列化为原来的带语言后缀的JSON结构,可以自定义转换器实现。

1. 简化实体类定义:

public class LocalizedItem
{
    public string Id { get; set; }
    // Key为语言后缀,Value为对应内容
    public Dictionary<string, List<string>> Descriptions { get; set; }
    public Dictionary<string, string> OfficialTitles { get; set; }
    public Dictionary<string, string> AuthTowns { get; set; }
}

2. 实现自定义转换器:

public class LocalizedItemConverter : JsonConverter<LocalizedItem>
{
    public override LocalizedItem ReadJson(JsonReader reader, Type objectType, LocalizedItem existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jObj = JObject.Load(reader);
        var item = new LocalizedItem
        {
            Id = jObj["id"]?.ToString(),
            Descriptions = new Dictionary<string, List<string>>(),
            OfficialTitles = new Dictionary<string, string>(),
            AuthTowns = new Dictionary<string, string>()
        };

        foreach (var prop in jObj.Properties())
        {
            if (prop.Name.StartsWith("descriptions_"))
            {
                var lang = prop.Name["descriptions_".Length..];
                item.Descriptions[lang] = prop.Value.ToObject<List<string>>();
            }
            else if (prop.Name.StartsWith("official_title_"))
            {
                var lang = prop.Name["official_title_".Length..];
                item.OfficialTitles[lang] = prop.Value.ToString();
            }
            else if (prop.Name.StartsWith("auth_town_"))
            {
                var lang = prop.Name["auth_town_".Length..];
                item.AuthTowns[lang] = prop.Value.ToString();
            }
        }
        return item;
    }

    public override void WriteJson(JsonWriter writer, LocalizedItem value, JsonSerializer serializer)
    {
        var jObj = new JObject { { "id", value.Id } };
        // 把字典序列化为带前缀的键
        foreach (var desc in value.Descriptions)
        {
            jObj.Add($"descriptions_{desc.Key}", JToken.FromObject(desc.Value));
        }
        foreach (var title in value.OfficialTitles)
        {
            jObj.Add($"official_title_{title.Key}", title.Value);
        }
        foreach (var town in value.AuthTowns)
        {
            jObj.Add($"auth_town_{town.Key}", town.Value);
        }
        jObj.WriteTo(writer);
    }
}

使用方式:

反序列化时传入转换器即可:

var result = JsonConvert.DeserializeObject<LocalizedItem>(yourJsonString, new LocalizedItemConverter());
// 序列化回原JSON结构示例
var outputJson = JsonConvert.SerializeObject(result, new LocalizedItemConverter());

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 23:54:03