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

如何使用JSON.NET将JSON数组中的对象名转为属性值?

解决JSON动态键到C#固定类的反序列化问题

这个场景其实是JSON反序列化里很常见的「动态键映射固定类」需求,完全不用靠多态来硬凑,自定义一个JSON转换器就能完美保留代码的灵活性。下面我用两种主流的.NET JSON序列化库分别给出解决方案:

方案一:使用Newtonsoft.Json(Json.NET)

Newtonsoft.Json支持自定义转换器,我们可以通过实现JsonConverter<Statistic>来处理这种动态键的情况:

1. 实现自定义转换器

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

public class StatisticConverter : JsonConverter<Statistic>
{
    public override Statistic ReadJson(JsonReader reader, Type objectType, Statistic existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        // 将当前JSON对象解析为JObject
        var jObject = JObject.Load(reader);
        // 获取唯一的键(题目说明所有键均唯一)
        var property = jObject.Properties().First();
        
        var statistic = new Statistic
        {
            Name = property.Name,
            // 从属性值中读取min和max
            Min = property.Value["min"].Value<int>(),
            Max = property.Value["max"].Value<int>()
        };
        
        return statistic;
    }

    public override void WriteJson(JsonWriter writer, Statistic value, JsonSerializer serializer)
    {
        // 如果需要将Statistic序列化为原JSON格式,实现这个方法
        var jObject = new JObject();
        var innerObject = new JObject
        {
            ["min"] = value.Min,
            ["max"] = value.Max
        };
        jObject[value.Name] = innerObject;
        jObject.WriteTo(writer);
    }
}

2. 在类中应用转换器

你可以直接在Container类的Statistics属性上标记转换器,或者在序列化/反序列化时指定:

public class Container
{
    // 给数组属性添加转换器,指定每个元素用StatisticConverter处理
    [JsonConverter(typeof(StatisticConverter))]
    public Statistic[] Statistics { get; set; }
}

public class Statistic
{
    public string Name { get; set; }
    public int Min { get; set; }
    public int Max { get; set; }
}

3. 测试反序列化

string json = @"{""statistics"": [ { ""Strength"": { ""min"": 16, ""max"": 20 } }, { ""Dexterity"": { ""min"": 16, ""max"": 20 } }]}";

Container container = JsonConvert.DeserializeObject<Container>(json);

// 输出测试
foreach (var stat in container.Statistics)
{
    Console.WriteLine($"Name: {stat.Name}, Min: {stat.Min}, Max: {stat.Max}");
}
// 会输出:
// Name: Strength, Min: 16, Max: 20
// Name: Dexterity, Min: 16, Max: 20

方案二:使用System.Text.Json(.NET Core/.NET 5+内置)

如果你用的是较新的.NET版本,也可以用内置的System.Text.Json实现自定义转换器:

1. 实现转换器

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

public class StatisticSystemTextConverter : JsonConverter<Statistic>
{
    public override Statistic Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        using (var jsonDoc = JsonDocument.ParseValue(ref reader))
        {
            var root = jsonDoc.RootElement;
            // 获取唯一的属性
            var property = root.EnumerateObject().First();
            
            return new Statistic
            {
                Name = property.Name,
                Min = property.Value.GetProperty("min").GetInt32(),
                Max = property.Value.GetProperty("max").GetInt32()
            };
        }
    }

    public override void Write(Utf8JsonWriter writer, Statistic value, JsonSerializerOptions options)
    {
        writer.WriteStartObject();
        writer.WriteStartObject(value.Name);
        writer.WriteNumber("min", value.Min);
        writer.WriteNumber("max", value.Max);
        writer.WriteEndObject();
        writer.WriteEndObject();
    }
}

2. 应用转换器

public class Container
{
    [JsonConverter(typeof(StatisticSystemTextConverter))]
    public Statistic[] Statistics { get; set; }
}

// 或者在序列化选项中全局添加转换器
var options = new JsonSerializerOptions();
options.Converters.Add(new StatisticSystemTextConverter());

// 反序列化示例
Container container = JsonSerializer.Deserialize<Container>(json, options);

核心思路说明

两种方案的逻辑本质是一致的:

  • 读取每个JSON数组元素中的单键对象
  • 提取这个动态键作为Statistic的Name属性
  • 从键对应的子对象中读取min和max值,填充到Statistic的对应字段

这种方式完全不需要为每种统计字段创建单独的类,不管后续新增多少种统计项(比如Luck、Intelligence),代码都能自动适配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.07 12:52:34