从图数据库获取动态对象反序列化JSON遇数组单值不匹配问题求解
解决Newtonsoft.Json数组转单个值的反序列化异常
你猜的完全没错——问题根源就是JSON里的每个字段值都是数组类型(比如["false"]),但你的MyObject类对应的属性是单个值类型(bool/string),Newtonsoft.Json默认不知道怎么把数组转换成单个值,所以抛出了那个JsonReaderException。
下面给你三种常用的解决方案,你可以根据自己的场景选择:
方案1:自定义Json转换器(推荐,一劳永逸)
写一个通用的转换器,自动从数组中提取第一个元素赋值给单个值属性。这种方法适合需要多次处理这类JSON的场景:
首先定义转换器类:
public class SingleValueArrayConverter<T> : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(T); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // 处理数组情况:读取数组第一个元素 if (reader.TokenType == JsonToken.StartArray) { reader.Read(); // 移动到数组第一个元素 var value = serializer.Deserialize<T>(reader); reader.Read(); // 跳过数组结束标记 return value; } // 如果遇到单个值(兼容非数组情况),直接返回 return serializer.Deserialize<T>(reader); } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // 如果需要序列化回数组格式,就保留这段;不需要的话可以直接序列化单个值 writer.WriteStartArray(); serializer.Serialize(writer, value); writer.WriteEndArray(); } }
然后给MyObject的属性加上转换器标记:
public class MyObject { [JsonConverter(typeof(SingleValueArrayConverter<bool>))] public bool FlagCalculateclientside { get; set; } [JsonConverter(typeof(SingleValueArrayConverter<string>))] public string Description { get; set; } [JsonConverter(typeof(SingleValueArrayConverter<string>))] public string Name { get; set; } }
这样原来的反序列化代码不需要修改,就能正常把数组值转换成单个属性值了。
方案2:手动转字典提取值(临时处理首选)
如果只是偶尔处理一次这类JSON,不想写转换器,可以先把JSON反序列化为字典,再手动提取数组的第一个元素:
var e = results.GetEnumerator(); while (e.MoveNext()) { var serialized = JsonConvert.SerializeObject(e.Current); // 先转成字典,键是字段名,值是JArray var fieldDict = JsonConvert.DeserializeObject<Dictionary<string, JArray>>(serialized); var val = new MyObject { FlagCalculateclientside = fieldDict["FlagCalculateclientside"].First.Value<bool>(), Description = fieldDict["Description"].First.Value<string>(), Name = fieldDict["Name"].First.Value<string>() }; }
方案3:修改类属性为数组类型
如果你可以修改MyObject的结构,并且需要保留原始的数组数据,可以把属性改成数组类型,再通过只读属性方便使用:
public class MyObject { public bool[] FlagCalculateclientside { get; set; } public string[] Description { get; set; } public string[] Name { get; set; } // 只读属性,方便获取第一个元素 public bool FlagCalculateclientsideValue => FlagCalculateclientside?.FirstOrDefault() ?? false; public string DescriptionValue => Description?.FirstOrDefault(); public string NameValue => Name?.FirstOrDefault(); }
这种方法反序列化不会报错,使用的时候直接用val.FlagCalculateclientsideValue就能拿到单个值了。
内容的提问来源于stack exchange,提问作者kanpeki
相关产品推荐
相关产品推荐

