如何反序列化含额外属性的JSON到NuGet类?兼容两大JSON库
解决方案:兼容双JSON库访问额外属性
前提回顾
无法修改NuGet提供的Base和Data类,JSON负载包含Data未定义的Value2属性,需同时兼容Newtonsoft.Json和System.Text.Json,且保留原有属性访问能力。
方案一:类型安全的派生类+扩展属性
通过创建派生类捕获额外属性,结合双库特性实现兼容。
1. 定义扩展类
创建继承自Data的扩展类,利用双库的扩展数据特性捕获未定义属性,并提供便捷访问:
public class ExtendedData : Data { // 适配Newtonsoft.Json的扩展属性标记 [Newtonsoft.Json.JsonExtensionData] // 适配System.Text.Json的扩展属性标记 [System.Text.Json.Serialization.JsonExtensionData] public IDictionary<string, object> ExtraData { get; set; } = new Dictionary<string, object>(); // 快速获取Value2的便捷属性 public string Value2 => ExtraData.TryGetValue("Value2", out var val) ? val.ToString() : null; } // 派生Base类,替换Data属性为ExtendedData类型 public class ExtendedBase : Base { public new ExtendedData Data { get; set; } }
2. Newtonsoft.Json 适配
Newtonsoft原生支持派生类属性重写的类型替换,直接反序列化即可:
var settings = new Newtonsoft.Json.JsonSerializerSettings { ObjectCreationHandling = Newtonsoft.Json.ObjectCreationHandling.Replace }; var extendedBase = Newtonsoft.Json.JsonConvert.DeserializeObject<ExtendedBase>(json, settings); // 访问原有属性 var value1 = extendedBase.Data.Value1; // 访问额外属性 var value2 = extendedBase.Data.Value2;
3. System.Text.Json 适配
System.Text.Json默认不支持属性重写的类型替换,需自定义转换器处理:
public class BaseConverter : System.Text.Json.Serialization.JsonConverter<ExtendedBase> { public override ExtendedBase Read(ref System.Text.Json.Utf8JsonReader reader, Type typeToConvert, System.Text.Json.JsonSerializerOptions options) { var jsonElement = System.Text.Json.JsonElement.ParseValue(ref reader); var extendedBase = new ExtendedBase(); // 反序列化基类原有属性(排除Data) var baseOptions = new System.Text.Json.JsonSerializerOptions(options); baseOptions.Converters.Remove(this); System.Text.Json.JsonSerializer.Deserialize(jsonElement.GetRawText(), extendedBase, baseOptions); // 单独反序列化Data为ExtendedData if (jsonElement.TryGetProperty("Data", out var dataElement)) { extendedBase.Data = System.Text.Json.JsonSerializer.Deserialize<ExtendedData>(dataElement.GetRawText(), options); } return extendedBase; } public override void Write(System.Text.Json.Utf8JsonWriter writer, ExtendedBase value, System.Text.Json.JsonSerializerOptions options) { // 序列化时保留原Base结构,同时写入Value2 System.Text.Json.JsonSerializer.Serialize(writer, (Base)value, options); writer.WriteString("Value2", value.Data.Value2); } }
使用方式:
var options = new System.Text.Json.JsonSerializerOptions { Converters = { new BaseConverter() }, PropertyNameCaseInsensitive = true }; var extendedBase = System.Text.Json.JsonSerializer.Deserialize<ExtendedBase>(json, options); // 访问方式同Newtonsoft
方案二:动态对象映射(快速实现)
无需定义派生类,通过动态对象直接提取额外属性,适合快速开发场景(无类型安全)。
Newtonsoft.Json 实现
dynamic dynamicObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json); var baseObj = Newtonsoft.Json.JsonConvert.DeserializeObject<Base>(json); string value2 = dynamicObj.Data.Value2; // baseObj访问原有属性,value2访问额外属性
System.Text.Json 实现
using var jsonDoc = System.Text.Json.JsonDocument.Parse(json); var baseObj = System.Text.Json.JsonSerializer.Deserialize<Base>(json); string value2 = jsonDoc.RootElement.GetProperty("Data").GetProperty("Value2").GetString(); // baseObj访问原有属性,value2访问额外属性
内容的提问来源于stack exchange,提问作者Gil
相关产品推荐
相关产品推荐

