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

如何使用Newtonsoft.Json将异构JSON反序列化为指定C#对象列表?

解决Newtonsoft.Json异构JSON反序列化到指定C#结构的问题

问题背景

给定如下异构JSON响应:

{"a374e91a9f513c79a8961de7c494cf799bbdb35b":{"rd":[{"1":{"filename":"The Lion King (2019) BluRay 1080p x264 (nItRo)-XpoZ.mkv","filesize":1819821931}}]},"e999ddbb3e18613476546684e34a4a6b0cfec878":{"rd":[{"1":{"filename":"The.Lion.King.2019.1080p.BluRay.10bit.x265-HazMatt.mkv","filesize":4256678521}}]},"8bb877768a0780c9694767a655720927e6cda57e":{"rd":[]},"054139ba17b8fdd8df1538e1857c45240d5c9368":[]}}

需要将其映射到以下C#对象结构:

public class Item
{
    public string Key { get; set; }
    public List<File> Files { get; set; }
}

public class File
{
    public string Id { get; set; }
    public string FileName { get; set; }
    public long FileSize { get; set; }
}

注意:JSON中类似rd的属性名不固定,可能会变化。

解决方案

由于JSON最外层是动态键的对象,且内层存在不确定属性名,无法直接反序列化为List<Item>,需通过以下步骤处理:

  1. 先将JSON反序列化为Dictionary<string, JToken>,获取所有顶层动态键值对;
  2. 遍历每个键值对,将键赋值给Item.Key;
  3. 处理每个值:
    • 若值为数组(如最后一个键对应的[]),则Files设为空列表;
    • 若值为对象,提取该对象的第一个值(忽略不确定的属性名),该值为文件数组;
    • 遍历文件数组中的每个元素,提取动态键作为File.Id,并映射filename和filesize到对应属性。

完整代码示例

using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System.Collections.Generic;
using System.Linq;

// 定义目标类
public class Item
{
    public string Key { get; set; }
    public List<File> Files { get; set; } = new List<File>(); // 初始化空列表避免空引用
}

public class File
{
    public string Id { get; set; }
    public string FileName { get; set; }
    public long FileSize { get; set; }
}

// 反序列化逻辑
string jsonResponse = "你的JSON字符串";
var jsonDict = JsonConvert.DeserializeObject<Dictionary<string, JToken>>(jsonResponse);

var items = new List<Item>();

foreach (var kvp in jsonDict)
{
    var item = new Item { Key = kvp.Key };

    if (kvp.Value.Type == JTokenType.Array)
    {
        items.Add(item);
        continue;
    }

    // 取对象中的第一个值(忽略不确定的属性名,如rd)
    var fileArrayToken = kvp.Value.Children().FirstOrDefault()?.Value<JArray>();
    if (fileArrayToken == null)
    {
        items.Add(item);
        continue;
    }

    foreach (var fileToken in fileArrayToken)
    {
        // 提取动态键作为File.Id
        var fileKvp = fileToken.Children<JProperty>().FirstOrDefault();
        if (fileKvp == null) continue;

        var fileData = fileKvp.Value.ToObject<FileData>();
        item.Files.Add(new File
        {
            Id = fileKvp.Name,
            FileName = fileData.Filename,
            FileSize = fileData.Filesize
        });
    }

    items.Add(item);
}

// 辅助类,用于临时映射文件属性
private class FileData
{
    [JsonProperty("filename")]
    public string Filename { get; set; }

    [JsonProperty("filesize")]
    public long Filesize { get; set; }
}

说明

  • 用Dictionary<string, JToken>接收顶层动态键,解决异构键的问题;
  • 通过JToken的类型判断和遍历子元素,避开不确定的内层属性名;
  • 辅助类FileData用于临时映射JSON中的filename和filesize,避免直接操作JToken的繁琐;
  • 初始化Item.Files为空列表,避免后续操作出现空引用异常。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 16:55:15