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" } ] ]
原因分析
- 动态类型解析异常:使用
dynamic作为泛型参数时,Json.NET会将对象解析为JObject实例。若后续直接对这些JObject进行序列化或未正确使用索引器访问属性,会出现值显示为空数组的问题。 - 类型匹配过于松散:原始JSON是嵌套的
List<List<object>>结构,IEnumerable<dynamic>的约束太宽泛,无法让Json.NET准确推断内部对象的类型,导致值解析失败。 - 属性名自动大小写转换: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
相关产品推荐
相关产品推荐

