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

JsonConvert.DeserializeObject反序列化值为空数组的问题排查

C# Json.NET反序列化值为空数组的问题原因及解决方法

问题详情

原始JSON数据结构如下:

[[{"id":1,"Name":"joy","School":"BMH","Class":"tenth"}],
 [{"order":1,"Name":"product1","DisplayName":"watch1","Columntype":"text1"}],
 [{"order":2,"Name":"product2","DisplayName":"watch2","Columntype":"text2"}]]

使用以下代码反序列化:

JsonConvert.DeserializeObject<List<IEnumerable<dynamic>>>(Reportdata[0])

得到的结果中所有属性值均为空数组,结构也不符合预期:

[
    [
        {
            "id": [],
            "Name": [],
            "School": [],
            "Class": []
        }
    ],
    [
        {
            "Order": [],
            "Name": [],
            "DisplayName": [],
            "ColumnType": []
        }
    ]
]

预期结果应为:

[
    [
        {
            "id": 1,
            "Name": "joy",
            "School": "BMH",
            "Class": "tenth"
        }
    ],
    [
        {
            "Order": 1,
            "Name": "product1",
            "DisplayName": "watch1",
            "ColumnType": "text1"
        },
        {
            "Order": 2,
            "Name": "product2",
            "DisplayName": "watch2",
            "ColumnType": "text2"
        }
    ]
]

原因分析

  1. 动态类型解析异常:使用dynamic作为泛型参数时,Json.NET会将对象解析为JObject实例。若后续直接对这些JObject进行序列化或未正确使用索引器访问属性,会出现值显示为空数组的问题。
  2. 类型匹配过于松散:原始JSON是嵌套的List<List<object>>结构,IEnumerable<dynamic>的约束太宽泛,无法让Json.NET准确推断内部对象的类型,导致值解析失败。
  3. 属性名自动大小写转换:Json.NET默认会将JSON中的驼峰命名(如order、Columntype)转换为帕斯卡命名(Order、ColumnType),这是显示上的差异,并非值为空的直接原因。

解决方案

方案1:用JObject替代dynamic

将反序列化目标类型改为List<List<JObject>>,可通过JObject索引器正确访问属性,后续序列化也能得到正常结果:

var result = JsonConvert.DeserializeObject<List<List<JObject>>>(Reportdata[0]);
// 属性访问示例
int studentId = (int)result[0][0]["id"];
string productName = (string)result[1][0]["Name"];

方案2:定义具体实体类

若JSON结构固定,定义对应实体类可获得类型安全的解析结果:

public class Student
{
    public int id { get; set; }
    public string Name { get; set; }
    public string School { get; set; }
    public string Class { get; set; }
}

public class Product
{
    public int order { get; set; }
    public string Name { get; set; }
    public string DisplayName { get; set; }
    public string Columntype { get; set; }
}

// 反序列化并转换为实体类
var rawResult = JsonConvert.DeserializeObject<List<List<object>>>(Reportdata[0]);
var student = ((JObject)rawResult[0][0]).ToObject<Student>();
var products = rawResult.Skip(1).Select(sub => ((JObject)sub[0]).ToObject<Product>()).ToList();

方案3:保留原始属性名大小写(可选)

若需要保留JSON中的原始属性名,可添加序列化设置:

var settings = new JsonSerializerSettings
{
    ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var result = JsonConvert.DeserializeObject<List<List<JObject>>>(Reportdata[0], settings);

额外处理:合并产品子数组

原始JSON中后两个产品是独立的单元素子数组,若要合并为一个包含两个对象的数组,可在反序列化后手动处理:

var mergedResult = new List<List<object>>
{
    rawResult[0],
    rawResult.Skip(1).SelectMany(sub => sub).ToList()
};

内容的提问来源于stack exchange,提问作者Gagan H M

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 05:28:16