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

如何用Newtonsoft.Json反序列化可变数组键的JSON到泛型类?

实现方案:动态捕获JSON数组属性名并映射到字典

当然可以实现这个需求,核心思路是不硬编码数组属性名,而是在反序列化过程中动态识别JSON中的数组类型属性,将属性名作为字典键、数组内容转为List<Friend>作为值存入目标属性。下面是两种实用的实现方式:

方案一:自定义Json转换器(推荐,通用可复用)

通过编写自定义JsonConverter,可以让Newtonsoft.Json在反序列化时自动处理动态属性名的映射,无需每次手动解析,适合批量处理20个JSON文件的场景。

1. 定义实体类

保留原有Person类的基础属性,将原List<Friend>替换为Dictionary<string, List<Friend>>:

public class Person
{
    // 原有的基础属性(示例)
    public string Name { get; set; }
    public int Age { get; set; }
    
    // 存储动态捕获的数组分组
    public Dictionary<string, List<Friend>> ContactGroups { get; set; } = new();
}

public class Friend
{
    public string FriendName { get; set; }
    public string Phone { get; set; }
}

2. 编写自定义转换器

继承JsonConverter<Person>,在ReadJson方法中解析JSON对象,提取所有数组类型的属性:

public class PersonDynamicGroupsConverter : JsonConverter<Person>
{
    public override Person ReadJson(JsonReader reader, Type objectType, Person existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var jsonObj = JObject.Load(reader);
        var person = existingValue ?? new Person();
        
        // 先反序列化基础属性(Name、Age等)
        serializer.Populate(jsonObj.CreateReader(), person);
        
        // 遍历所有JSON属性,筛选出数组类型的项
        foreach (var prop in jsonObj.Properties())
        {
            if (prop.Value.Type == JTokenType.Array)
            {
                // 将数组转为List<Friend>,存入字典
                var friendList = prop.Value.ToObject<List<Friend>>(serializer);
                person.ContactGroups[prop.Name] = friendList;
            }
        }
        
        return person;
    }

    public override void WriteJson(JsonWriter writer, Person value, JsonSerializer serializer)
    {
        // 如果需要将Person序列化回JSON,可在这里实现反向逻辑
        var jsonObj = JObject.FromObject(value, serializer);
        foreach (var group in value.ContactGroups)
        {
            jsonObj.Add(group.Key, JArray.FromObject(group.Value, serializer));
        }
        jsonObj.WriteTo(writer);
    }
}

3. 使用转换器反序列化

反序列化时指定自定义转换器即可:

// 读取任意一个JSON文件
var jsonContent = File.ReadAllText("sample.json");
var person = JsonConvert.DeserializeObject<Person>(jsonContent, new PersonDynamicGroupsConverter());

// 遍历字典查看捕获的属性名和对应好友列表
foreach (var group in person.ContactGroups)
{
    Console.WriteLine($"分组属性名:{group.Key}");
    foreach (var friend in group.Value)
    {
        Console.WriteLine($"  好友:{friend.FriendName}");
    }
}

方案二:手动解析JObject(快速实现,灵活可控)

如果不需要复用转换器,也可以直接将JSON解析为JObject,手动提取数组属性并映射到Person类:

var jsonContent = File.ReadAllText("sample.json");
var jsonObj = JObject.Parse(jsonContent);

var person = new Person
{
    Name = jsonObj["Name"]?.ToString(),
    Age = jsonObj["Age"]?.ToObject<int>() ?? 0,
    ContactGroups = new()
};

// 遍历所有属性,筛选数组类型
foreach (var prop in jsonObj.Properties())
{
    if (prop.Value.Type == JTokenType.Array)
    {
        person.ContactGroups[prop.Name] = prop.Value.ToObject<List<Friend>>();
    }
}

方案对比

  • 自定义转换器:一次编写,多次复用,代码结构更清晰,适合批量处理多个JSON文件的场景。
  • 手动解析JObject:代码更简洁,无需额外编写转换器,适合临时或简单场景。

两种方案都能完美满足你的需求:动态捕获所有不同的数组属性名(如friends、mates、companions),并将对应数组内容存入字典中。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 16:00:59