You need to enable JavaScript to run this app. 如何使用System.Text.Json将动态键值JSON反序列化至指定自定义类结构
优惠活动
大模型
产品
解决方案
定价
更多

如何使用System.Text.Json将动态键值JSON反序列化至指定自定义类结构

System.Text.Json 实现动态键JSON映射的方案

核心目标是将warnings节点下的动态字符串键(数字形式的区域ID)、对应数组值的结构,映射到已定义的三层类结构,全程无侵入修改原有业务类。

方案1:自定义原生JsonConverter(双向兼容,可复用)

System.Text.Json 对非标准结构映射的核心能力是自定义转换器,基于高性能的Utf8JsonReader/Utf8JsonWriter实现,对原有Root/WarningArea/Warning类无需做任何修改。

首先实现针对Root类型的自定义转换器:

using System.Text.Json;
using System.Text.Json.Serialization;

public class RootJsonConverter : JsonConverter<Root>
{
    public override Root Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var warningAreas = new List<WarningArea>();
        
        while (reader.Read())
        {
            // 遍历到最外层对象结尾时退出
            if (reader.TokenType == JsonTokenType.EndObject)
                break;

            // 定位到warnings节点
            if (reader.TokenType == JsonTokenType.PropertyName && reader.GetString() == "warnings")
            {
                reader.Read();
                if (reader.TokenType != JsonTokenType.StartObject)
                    continue;

                // 遍历warnings下的所有动态属性
                while (reader.Read())
                {
                    if (reader.TokenType == JsonTokenType.EndObject)
                        break;

                    if (reader.TokenType == JsonTokenType.PropertyName)
                    {
                        string areaIdStr = reader.GetString();
                        reader.Read();

                        // 反序列化当前键对应的Warning数组
                        if (reader.TokenType == JsonTokenType.StartArray)
                        {
                            var warnings = JsonSerializer.Deserialize<List<Warning>>(ref reader, options);
                            
                            // 容错转换ID,非数字键自动跳过
                            if (int.TryParse(areaIdStr, out int areaId))
                            {
                                warningAreas.Add(new WarningArea
                                {
                                    AreaId = areaId,
                                    Warnings = warnings ?? new List<Warning>()
                                });
                            }
                        }
                    }
                }
            }
        }

        return new Root { WarningAreas = warningAreas };
    }

    public override void Write(Utf8JsonWriter writer, Root value, JsonSerializerOptions options)
    {
        // 配套实现序列化逻辑,自动还原为原JSON结构
        writer.WriteStartObject();
        writer.WritePropertyName("warnings");
        writer.WriteStartObject();
        
        foreach (var area in value.WarningAreas)
        {
            writer.WritePropertyName(area.AreaId.ToString());
            JsonSerializer.Serialize(writer, area.Warnings, options);
        }
        
        writer.WriteEndObject();
        writer.WriteEndObject();
    }
}

注册转换器后直接使用即可:

var jsonOptions = new JsonSerializerOptions
{
    Converters = { new RootJsonConverter() },
    // 按需添加其他配置
    PropertyNameCaseInsensitive = true
};

// 反序列化
var result = JsonSerializer.Deserialize<Root>(原始JSON字符串, jsonOptions);

方案2:手动映射(轻量场景适用)

如果仅需要反序列化、不需要双向支持,不需要写自定义转换器,可利用原生Dictionary对动态键的直接映射能力,手动完成结构转换:

// 定义临时匹配结构
internal class TempRoot
{
    public Dictionary<int, List<Warning>> Warnings { get; set; }
}

// 反序列化临时结构
var tempResult = JsonSerializer.Deserialize<TempRoot>(原始JSON字符串, new JsonSerializerOptions
{
    PropertyNameCaseInsensitive = true
});

// 转换为目标类结构
var root = new Root
{
    WarningAreas = tempResult.Warnings.Select(kv => new WarningArea
    {
        AreaId = kv.Key,
        Warnings = kv.Value
    }).ToList()
};

注意事项

  • 自定义转换器的实现全程基于System.Text.Json原生高性能API,无第三方依赖,性能高于Newtonsoft.Json的同逻辑实现
  • 自定义转换器中加入了类型转换容错逻辑,遇到非数字格式的动态键会自动跳过,不会导致整个反序列化流程异常
  • 两种方案都不需要修改预先定义的Root、WarningArea、Warning类的代码,无业务侵入

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.04 22:06:04