C#使用Newtonsoft.Json反序列化JSON时嵌套字典转换报错如何解决
问题原因
报错是因为JSON中的rights字段存储的是转义后的JSON字符串,不是标准的字典对象结构,Newtonsoft.Json默认不会自动对嵌套的JSON字符串执行二次反序列化。
最优实现方案:自定义JsonConverter
该方案侵入性低、可复用,不需要修改原有类的业务逻辑,一次定义可在所有同场景下使用。
第一步:定义自定义转换器
using Newtonsoft.Json; using System; using System.Collections.Generic; public class StringToDictionaryConverter : JsonConverter<Dictionary<int, long>> { public override Dictionary<int, long> ReadJson(JsonReader reader, Type objectType, Dictionary<int, long> existingValue, bool hasExistingValue, JsonSerializer serializer) { // 读取到字符串时先执行二次反序列化 if (reader.TokenType == JsonToken.String) { string jsonStr = reader.Value?.ToString(); return string.IsNullOrEmpty(jsonStr) ? new Dictionary<int, long>() : JsonConvert.DeserializeObject<Dictionary<int, long>>(jsonStr); } // 本身是字典结构时走默认反序列化逻辑 if (reader.TokenType == JsonToken.StartObject) { return serializer.Deserialize<Dictionary<int, long>>(reader); } return default; } public override void WriteJson(JsonWriter writer, Dictionary<int, long> value, JsonSerializer serializer) { // 序列化时如果需要转回字符串格式就启用下面的代码,不需要就走默认序列化逻辑 // writer.WriteValue(JsonConvert.SerializeObject(value)); serializer.Serialize(writer, value); } }
第二步:绑定转换器到属性
在你的A类的rights属性上添加JsonConverter特性即可:
public class A { public Guid userId { get; set; } public Guid businessId { get; set; } [JsonConverter(typeof(StringToDictionaryConverter))] public Dictionary<int, long> rights { get; set; } }
配置完成后直接调用JsonConvert.DeserializeObject<A>(json)即可正常反序列化,不需要额外处理。
其他可选方案
如果不想新增转换器类,也可以通过属性中转实现:
public class A { public Guid userId { get; set; } public Guid businessId { get; set; } [JsonProperty("rights")] public string RightsJson { get; set; } [JsonIgnore] public Dictionary<int, long> rights => string.IsNullOrEmpty(RightsJson) ? new Dictionary<int, long>() : JsonConvert.DeserializeObject<Dictionary<int, long>>(RightsJson); }
该方案不需要额外定义转换器,但会在类中增加业务无关的中转属性,不如自定义转换器优雅。
内容的提问来源于stack exchange,提问作者Muhammad Jamali
相关产品推荐
相关产品推荐

