使用JsonConvert反序列化时,如何将JSON中可变结构的Other节点保留为原始文本字符串?
解决方案:将可变结构的JSON节点反序列化为原始字符串
当然有办法实现这个需求!针对你遇到的可变other节点场景,这里有两种实用的方案,都能完美将该节点的原始JSON文本存入字符串字段:
方案一:自定义JsonConverter(推荐,支持双向序列化)
这种方法通过自定义转换器,直接把other对应的JSON对象读取为字符串,同时也支持后续将字符串序列回JSON,非常适合需要存入数据库后再取出使用的场景。
步骤1:实现自定义转换器
public class RawJsonConverter : JsonConverter { // 指定该转换器仅处理Other类型 public override bool CanConvert(Type objectType) { return objectType == typeof(Other); } // 反序列化:将JSON节点转为原始字符串 public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var jsonToken = JToken.Load(reader); return new Other { AllFieldsFromOtherSectionAsRawText = jsonToken.ToString(Formatting.None) }; } // 序列化:将字符串转回JSON节点(如果需要把数据写回JSON时有用) public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { var otherObj = value as Other; if (!string.IsNullOrWhiteSpace(otherObj.AllFieldsFromOtherSectionAsRawText)) { var jsonToken = JToken.Parse(otherObj.AllFieldsFromOtherSectionAsRawText); jsonToken.WriteTo(writer); } else { writer.WriteNull(); } } }
步骤2:给Other类添加转换器特性
修改你的Other类,加上[JsonConverter]特性指定我们刚写的转换器:
[JsonConverter(typeof(RawJsonConverter))] public class Other { public string AllFieldsFromOtherSectionAsRawText { get; set; } }
之后你原来的反序列化代码var root = JsonConvert.DeserializeObject<Root>(JsonContent);完全不用改,执行后root.results.events里每个Event的other.AllFieldsFromOtherSectionAsRawText就会是对应节点的原始JSON字符串。
方案二:使用JToken临时存储(更简洁,适合只读场景)
如果只需要反序列化读取原始字符串,不需要后续序列化回去,可以用Newtonsoft.Json的JToken类型来临时承载JSON结构,再转成字符串:
修改Other类如下:
public class Other { // 对外暴露的原始字符串字段 [JsonIgnore] public string AllFieldsFromOtherSectionAsRawText => _rawJson?.ToString(Formatting.None); // 内部用JToken接收JSON数据,标记为private避免外部访问 [JsonProperty("other")] private JToken _rawJson { get; set; } }
这种方式不需要写额外的转换器,代码更简洁,但因为用了[JsonIgnore],如果后续需要把Other对象序列回JSON,AllFieldsFromOtherSectionAsRawText不会被序列化(如果有这个需求,还是方案一更合适)。
验证效果
反序列化后,你会得到如下结果:
- 第一个
Event的other.AllFieldsFromOtherSectionAsRawText值为:{"Red":"red","Green":"green","Blue":"blue"} - 第二个
Event的other.AllFieldsFromOtherSectionAsRawText值为:{"Yelow":"yellow","Orange":"orange"}
完全符合你把可变节点存为原始文本的需求,后续存入数据库也非常方便。
内容的提问来源于stack exchange,提问作者Milos
相关产品推荐
相关产品推荐

