C#动态反序列化多类型JSON字段的技术问题求助
动态反序列化多结构Readings字段的解决方案
问题核心原因
你遇到的报错本质是:第一次反序列化List<NodeResponse>时,若Readings字段定义为object或其他固定类型,Newtonsoft.Json会自动将原始JSON结构(数组/对象)转换为对应CLR类型(比如JArray),后续再尝试将其反序列化为需要JSON对象的VoltageReadingsV1时,类型不匹配导致失败。
方案一:保留原始JSON结构后动态转换
1. 调整NodeResponse类定义
将Readings字段类型改为JToken(Newtonsoft.Json.Linq命名空间下的类型),确保第一次反序列化时完整保留原始JSON的结构信息:
public class NodeResponse { public string Type { get; set; } public JToken Readings { get; set; } // 其他业务字段... }
2. 基于Type字段动态反序列化
反序列化完列表后,根据每个节点的Type值,将JToken转换为对应目标类型:
// 第一步:反序列化得到节点列表 var nodeResponses = JsonConvert.DeserializeObject<List<NodeResponse>>(rawJson); // 第二步:遍历处理每个节点 foreach (var node in nodeResponses) { switch (node.Type) { case "VoltageV1": var voltageData = node.Readings.ToObject<VoltageReadingsV1>(); // 处理电压读数逻辑 break; case "CurrentV2": var currentData = node.Readings.ToObject<CurrentReadingsV2>(); // 处理电流读数逻辑 break; // 其他已整理的类型分支... default: // 未知类型的 fallback 逻辑 break; } }
方案二:自定义JsonConverter自动处理
如果不想手动写分支逻辑,可以自定义转换器,在第一次反序列化时直接完成类型匹配:
1. 定义读数类型的基接口
让所有Readings类型实现统一接口,方便后续类型约束:
public interface ILoggerReadings { } public class VoltageReadingsV1 : ILoggerReadings { // 电压读数的字段定义 } public class CurrentReadingsV2 : ILoggerReadings { // 电流读数的字段定义 }
2. 修改NodeResponse类
public class NodeResponse { public string Type { get; set; } public ILoggerReadings Readings { get; set; } // 其他业务字段... }
3. 实现自定义转换器
public class ReadingsTypeConverter : JsonConverter<ILoggerReadings> { // 预定义类型映射表,对应你整理的所有类型 private readonly Dictionary<string, Type> _typeMapping = new() { { "VoltageV1", typeof(VoltageReadingsV1) }, { "CurrentV2", typeof(CurrentReadingsV2) } // 其他类型映射项... }; public override ILoggerReadings ReadJson(JsonReader reader, Type objectType, ILoggerReadings existingValue, bool hasExistingValue, JsonSerializer serializer) { // 加载整个节点的JSON对象 var jNode = JObject.Load(reader); var typeFlag = jNode["Type"]?.Value<string>(); if (string.IsNullOrEmpty(typeFlag) || !_typeMapping.TryGetValue(typeFlag, out var targetType)) { throw new JsonSerializationException($"Unsupported readings type: {typeFlag}"); } // 反序列化Readings字段为目标类型 return (ILoggerReadings)jNode["Readings"].ToObject(targetType, serializer); } public override void WriteJson(JsonWriter writer, ILoggerReadings value, JsonSerializer serializer) { // 如果需要序列化回JSON,在此实现对应逻辑 serializer.Serialize(writer, value); } }
4. 使用转换器完成反序列化
var serializerSettings = new JsonSerializerSettings { Converters = new List<JsonConverter> { new ReadingsTypeConverter() } }; var nodeResponses = JsonConvert.DeserializeObject<List<NodeResponse>>(rawJson, serializerSettings);
内容的提问来源于stack exchange,提问作者Niki Gagliardi
相关产品推荐
相关产品推荐

