如何用Json.Net自动反序列化两种格式存储的Values类对象?
这问题我之前处理过类似的场景,用自定义JsonConverter完全能搞定!核心思路就是在反序列化时判断输入的JSON是字符串还是对象,然后分别做处理。下面给你唠唠具体实现步骤,分两种常用的JSON库来讲解:
方案一:使用Newtonsoft.Json(Json.NET)
这是.NET生态里最常用的JSON处理库,实现起来很直观:
1. 自定义JsonConverter类
这个转换器会负责判断JSON类型,分别处理字符串和对象两种情况:
using System; using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; public class ValuesConverter : JsonConverter<Values> { public override Values ReadJson(JsonReader reader, Type objectType, Values existingValue, bool hasExistingValue, JsonSerializer serializer) { // 先判断当前JSON的token类型 if (reader.TokenType == JsonToken.String) { // 如果是字符串,直接构造Values实例 string singleValue = (string)reader.Value; return new Values { BestValue = 0, // 这里可以根据你的业务需求设置默认值 AllValues = new List<string> { singleValue } }; } else if (reader.TokenType == JsonToken.StartObject) { // 如果是对象,用JObject转成Values实例 JObject jObject = JObject.Load(reader); return jObject.ToObject<Values>(serializer); } // 遇到未知类型可以抛异常或者返回null,根据需求调整 throw new JsonSerializationException("反序列化Values时遇到意外的Token类型"); } public override void WriteJson(JsonWriter writer, Values value, JsonSerializer serializer) { // 序列化时也可以做反向处理:如果AllValues只有一个元素,就序列化成字符串 if (value.AllValues != null && value.AllValues.Count == 1) { writer.WriteValue(value.AllValues[0]); } else { // 否则正常序列化成对象 serializer.Serialize(writer, value); } } }
2. 应用转换器
有两种方式可以让转换器生效:
方式一:给Values类加特性标记
直接在类上标注转换器,这样所有序列化/反序列化操作都会自动用它:
[JsonConverter(typeof(ValuesConverter))] public class Values { public int BestValue { get; set; } public List<string> AllValues { get; set; } }
方式二:序列化/反序列化时手动指定
如果不想全局生效,也可以在调用方法时传入转换器:
// 反序列化字符串格式的JSON string singleValueJson = "\"MyFirstValue\""; Values singleValue = JsonConvert.DeserializeObject<Values>(singleValueJson, new ValuesConverter()); // 反序列化对象格式的JSON string objectJson = "{\"BestValue\" : 0, \"AllValues\" : [\"DefaultValue\", \"OtherValue\"]}"; Values objectValue = JsonConvert.DeserializeObject<Values>(objectJson, new ValuesConverter());
方案二:使用System.Text.Json(.NET Core 3.0+内置)
如果用的是.NET Core或.NET 5+的内置JSON库,实现思路类似,只是接口略有不同:
1. 自定义JsonConverter类
using System; using System.Collections.Generic; using System.Text.Json; using System.Text.Json.Serialization; public class ValuesConverter : JsonConverter<Values> { public override Values Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { string singleValue = reader.GetString(); return new Values { BestValue = 0, AllValues = new List<string> { singleValue } }; } else if (reader.TokenType == JsonTokenType.StartObject) { // 直接用内置方法反序列化对象 return JsonSerializer.Deserialize<Values>(ref reader, options); } throw new JsonException("反序列化Values时遇到意外的Token类型"); } public override void Write(Utf8JsonWriter writer, Values value, JsonSerializerOptions options) { if (value.AllValues != null && value.AllValues.Count == 1) { writer.WriteStringValue(value.AllValues[0]); } else { JsonSerializer.Serialize(writer, value, options); } } }
2. 应用转换器
同样有两种方式:
方式一:给类加特性标记
[JsonConverter(typeof(ValuesConverter))] public class Values { public int BestValue { get; set; } public List<string> AllValues { get; set; } }
方式二:通过JsonSerializerOptions指定
var options = new JsonSerializerOptions(); options.Converters.Add(new ValuesConverter()); // 反序列化字符串格式 Values singleValue = JsonSerializer.Deserialize<Values>("\"MyFirstValue\"", options); // 反序列化对象格式 Values objectValue = JsonSerializer.Deserialize<Values>("{\"BestValue\" : 0, \"AllValues\" : [\"DefaultValue\", \"OtherValue\"]}", options);
小提示
- 关于
BestValue的默认值:如果字符串场景下需要设置其他默认值(比如1或者-1),直接修改转换器里对应的值就行。 - 异常处理:如果遇到除了字符串和对象之外的类型,你可以根据业务需求选择返回null或者抛出更具体的异常。
内容的提问来源于stack exchange,提问作者Jean
相关产品推荐
相关产品推荐

