C#使用Newtonsoft.Json序列化反序列化Dictionary报错解决方法
问题原因
- 报错的核心是反序列化时传入的JSON结构和目标类型
Dictionary<string,string>要求的结构不匹配:Newtonsoft.Json反序列化字典时,要求输入必须是{}包裹的标准JSON对象(键值对结构),如果传入的是[]包裹的JSON数组,就会抛出你看到的异常。 - 你后续尝试调用
ToArray()再序列化的方案是完全错误的方向:ToArray()会把字典转成KeyValuePair<string,string>类型的数组,序列化后输出的是[]包裹的、由带Key/Value属性的对象组成的数组,本身就不是字典需要的对象结构,自然会触发完全相同的异常。 - 你初始代码中直接给字符串变量
json赋值裸{...}结构的写法不符合C#语法,实际运行时写入文件的内容大概率是之前逻辑生成的错误数组格式内容,才会导致第一次反序列化就报错。
正确实现方法
Newtonsoft.Json原生支持Dictionary<string, string>和标准JSON对象的互转,不需要做额外的数组转换,直接按以下逻辑实现即可:
序列化写入
public static Dictionary<string, string> dictionary { get; private set; } = new(); // 给字典填充值 dictionary.Add("1", "Some"); dictionary.Add("2222", "Data"); dictionary.Add("4123", "In"); dictionary.Add("107", "That"); dictionary.Add("4213213", "Json"); // 直接序列化字典,不要调用ToArray/ToList string json = Newtonsoft.Json.JsonConvert.SerializeObject(dictionary, Formatting.Indented); // 写入文件 File.WriteAllText("dictionary.json", json);
序列化后生成的JSON是标准对象结构,和你预期的格式完全一致:
{ "1": "Some", "2222": "Data", "4123": "In", "107": "That", "4213213": "Json" }
反序列化读取
// 读取文件内容 string fileContents = File.ReadAllText("dictionary.json"); // 直接反序列化为字典 dictionary = Newtonsoft.Json.JsonConvert.DeserializeObject<Dictionary<string, string>>(fileContents); // 直接通过索引取值即可 string value = dictionary["1"]; // 得到结果"Some"
特殊场景兼容
如果你已经有历史存量数据是之前错误生成的Key/Value数组格式,可以用以下逻辑兼容读取,再转成字典:
// 兼容旧的数组格式JSON var kvArray = Newtonsoft.Json.JsonConvert.DeserializeObject<KeyValuePair<string, string>[]>(fileContents); dictionary = kvArray.ToDictionary(item => item.Key, item => item.Value);
注意事项
- 序列化字典前不要调用
ToArray()、ToList()这类会把字典转成集合数组的方法,否则生成的JSON结构无法直接反序列化为字典。 - 如果之前测试时已经把错误格式的JSON写入了目标文件,一定要先删除旧文件或用正确序列化生成的内容覆盖旧文件,否则读取旧的错误内容还是会抛出异常。
- 反序列化前可以快速检查读取到的字符串首尾字符:如果首尾是
[和]就说明是数组格式,如果是{和}才是符合字典要求的对象格式。
内容的提问来源于stack exchange,提问作者Anton Kuznetsov
相关产品推荐
相关产品推荐

