如何将JSON解析为C#并正确取数?我的反序列化方法为何失效
嘿,我来帮你把这个JSON反序列化的问题理清楚!你遇到的错误其实是类型不匹配导致的,咱们一步步拆解解决:
先搞懂你之前踩的两个坑
直接反序列化数组时的InvalidCast异常
你一开始的JSON是[{...}, {...}]这种根级数组,但你用了反序列化成Dictionary的方法——这就好比把一箱苹果硬塞进橘子盒子,肯定装不下!因为JSON数组对应C#里的List<T>或数组T[],而Dictionary是对应JSON键值对对象的,类型完全不匹配,所以会抛出无法转换的异常。修改JSON后拿到字典但没法访问数组
你改成{"array": "[{...}, {...}]"}后,异常消失了,但这里有个隐藏问题:你把数组变成了字符串(注意外面的引号),而不是原生的JSON数组。所以反序列化后,字典里的"array"对应的值其实是一串文本,不是可直接遍历的数组。要解决这个,你应该把JSON改成{"array": [{...}, {...}]}(去掉数组外面的引号,让它成为真正的JSON数组)。
正确的反序列化方法(分两种场景)
场景1:JSON根是数组([{...}, {...}])
这种情况最直接的方式是定义一个对应数组元素的实体类,然后反序列化成List<实体类>:
假设你的JSON数组元素是用户信息,先定义类:
public class User { // 属性名要和JSON里的键名对应,也可以用特性指定映射 public string Username { get; set; } public int Score { get; set; } }
用.NET自带的System.Text.Json(.NET Core/.NET 5+可用)反序列化:
string jsonArray = @"[{""Username"":""Alex"",""Score"":95},{""Username"":""Mia"",""Score"":88}]"; List<User> userList = JsonSerializer.Deserialize<List<User>>(jsonArray); // 访问数据示例 foreach (var user in userList) { Console.WriteLine($"{user.Username} 的分数是 {user.Score}"); }
如果用Newtonsoft.Json(Json.NET),代码更简洁:
List<User> userList = JsonConvert.DeserializeObject<List<User>>(jsonArray);
场景2:JSON根是包含数组的对象({"array": [{...}, {...}]})
这种情况有两种处理方式:
方式1:定义根实体类(推荐,类型安全)
public class RootData { // 属性名要和JSON里的键名对应,比如这里的"array" public List<User> Array { get; set; } }
然后反序列化:
string jsonRoot = @"{""array"": [{""Username"":""Alex"",""Score"":95},{""Username"":""Mia"",""Score"":88}]}"; RootData root = JsonSerializer.Deserialize<RootData>(jsonRoot); // 访问数组里的数据 foreach (var user in root.Array) { Console.WriteLine($"{user.Username} 的分数是 {user.Score}"); }
方式2:用Dictionary(适合临时快速处理)
如果你不想定义类,可以直接反序列化成Dictionary<string, List<User>>:
var dataDict = JsonSerializer.Deserialize<Dictionary<string, List<User>>>(jsonRoot); List<User> userList = dataDict["array"]; // 后续访问和场景1一样
如果不知道JSON结构,想动态访问数据
如果你不确定JSON的具体结构,可以用JsonElement(System.Text.Json)或者dynamic类型(Newtonsoft.Json支持更好):
用JsonElement(类型安全)
string jsonArray = @"[{""Username"":""Alex"",""Score"":95},{""Username"":""Mia"",""Score"":88}]"; JsonElement root = JsonSerializer.Deserialize<JsonElement>(jsonArray); if (root.ValueKind == JsonValueKind.Array) { foreach (var element in root.EnumerateArray()) { string username = element.GetProperty("Username").GetString(); int score = element.GetProperty("Score").GetInt32(); Console.WriteLine($"{username} 的分数是 {score}"); } }
用dynamic(快速但无类型检查)
dynamic userList = JsonConvert.DeserializeObject(jsonArray); foreach (var user in userList) { Console.WriteLine($"{user.Username} 的分数是 {user.Score}"); }
总结核心要点
- JSON数组对应C#的
List<T>或T[],JSON键值对对象对应Dictionary<K,V>或自定义实体类 - 不要把JSON数组转换成字符串存入JSON,要保持原生的数组结构
- 优先用实体类反序列化,类型更安全,代码可读性更高
内容的提问来源于stack exchange,提问作者Александр Копаевич

