C#反序列化嵌套JSON数组遇Null值及序列化异常求助
解决方案:正确读取JSON嵌套数组并避免序列化异常
问题根源
你的JSON里actions、reactions、legendary_actions、special_abilities是数组类型(用[]包裹),但你定义的C#类里把这些字段声明成了ActionList这类自定义对象类型,Newtonsoft.Json会尝试把JSON数组当成对象反序列化,所以抛出异常;之前的null值也是因为类结构和JSON不匹配,无法正确映射数组数据。
步骤1:修正C#类定义
把原来的自定义列表类(比如ActionList)直接替换成List<T>类型,确保和JSON数组结构对应。示例如下:
原错误类结构(简化版)
public class MonsterOld { // 错误:用自定义对象对应JSON数组 public ActionList actions { get; set; } public SpecialAbilityList special_abilities { get; set; } public class ActionList { public List<Action> Actions { get; set; } } public class SpecialAbilityList { public List<SpecialAbility> SpecialAbilities { get; set; } } }
修正后的类结构
using System.Collections.Generic; using Newtonsoft.Json; // 主类:直接用List<T>对应JSON里的数组字段 public class MonsterOld { public string name { get; set; } public int hit_points { get; set; } // 直接用List<Action>匹配JSON数组 public List<Action> actions { get; set; } public List<Reaction> reactions { get; set; } public List<LegendaryAction> legendary_actions { get; set; } public List<SpecialAbility> special_abilities { get; set; } } // 嵌套数组的子元素类:属性和JSON字段一一对应 public class Action { public string name { get; set; } public string desc { get; set; } public int attack_bonus { get; set; } // 其他JSON里有的属性都加上 } public class SpecialAbility { public string name { get; set; } public string desc { get; set; } } public class Reaction { public string name { get; set; } public string desc { get; set; } } public class LegendaryAction { public string name { get; set; } public string desc { get; set; } }
如果JSON字段和C#属性名大小写不匹配(比如JSON是action_name,C#是ActionName),可以用[JsonProperty]特性强制绑定:
public class Action { [JsonProperty("action_name")] public string ActionName { get; set; } }
步骤2:正确反序列化JSON
类结构修正后,用Newtonsoft.Json的反序列化方法就能正确读取嵌套数组,不会再报错:
// 读取JSON文件内容 string jsonContent = File.ReadAllText("your-monster-file.json"); // 反序列化到修正后的MonsterOld类 MonsterOld monster = JsonConvert.DeserializeObject<MonsterOld>(jsonContent);
此时monster.actions、monster.special_abilities等字段会正确加载数组数据,不会是null(如果JSON里对应数组存在的话)。
步骤3:转换为后续项目需要的格式
假设你需要把MonsterOld转换成MonsterNew类型,直接遍历嵌套数组即可,注意用?.处理可能的null值(避免空引用异常):
public MonsterNew ConvertToTargetFormat(MonsterOld oldMonster) { if (oldMonster == null) return null; return new MonsterNew { MonsterName = oldMonster.name, HitPoints = oldMonster.hit_points, // 转换actions数组 Actions = oldMonster.actions?.Select(a => new ActionNew { Name = a.name, Description = a.desc, AttackBonus = a.attack_bonus }).ToList(), // 同理转换其他嵌套数组 SpecialAbilities = oldMonster.special_abilities?.Select(sa => new SpecialAbilityNew { AbilityName = sa.name, AbilityDesc = sa.desc }).ToList() }; } // 后续项目用的目标类示例 public class MonsterNew { public string MonsterName { get; set; } public int HitPoints { get; set; } public List<ActionNew> Actions { get; set; } public List<SpecialAbilityNew> SpecialAbilities { get; set; } } public class ActionNew { public string Name { get; set; } public string Description { get; set; } public int AttackBonus { get; set; } }
关键注意事项
- 始终保持C#类结构和JSON结构严格对应:JSON是数组用
List<T>/T[],JSON是对象用自定义类。 - 反序列化后先检查主对象是否为null,再访问嵌套字段。
- 如果JSON里可能存在空数组或缺失字段,用
?.运算符安全访问,避免程序崩溃。
内容的提问来源于stack exchange,提问作者Sam Pauley
相关产品推荐
相关产品推荐

