C#中如何正确建模指定JSON数据以实现JsonConvert反序列化
C# JSON反序列化建模问题解答
结论先行
你给出的两种建模方式都无法正确反序列化目标JSON。
原始JSON结构拆解
先明确你提供的JSON的实际结构:
{ "timestamp": "2021-10-20T17:46:13", "data": [ // 该字段本质上是一个字典结构 {"Pressure": 0.11}, {"Temp A": 47.88}, {"Temp B": 46.69} ] }
字段对应规则:
- 顶层
timestamp是ISO 8601格式的时间字符串,可以直接映射为C#的DateTime类型 - 顶层
data是数组类型,数组内每个元素都是仅包含一组键值对的对象,键为指标名称(字符串),值为浮点型数值
两种错误建模的问题说明
- 第一种建模方式错误点:
把data字段映射为自定义PayloadData类型,但JSON中data直接是数组,不是包含Data属性的嵌套对象,类型完全不匹配,反序列化会直接抛出异常;同时PayloadData类中定义的Data属性在JSON中没有对应字段,根本无法读取到值。 - 第二种建模方式错误点:
属性名定义为PayloadData,但JSON中对应字段的键名是data,默认反序列化规则下无法匹配到字段,最终该属性会被赋值为null。
正确建模方案
方案1:严格匹配JSON原生结构(无额外配置,直接可用)
这是最通用、不需要任何自定义转换的写法,直接适配JSON的原生结构,使用你给出的JsonConvert.DeserializeObject代码即可成功反序列化:
public class PayloadModel { public DateTime Timestamp { get; set; } // 属性名和JSON字段对应,类型匹配数组结构 public List<Dictionary<string, float>> Data { get; set; } }
如果你确实需要把数组合并为单个字典(对应你注释里提到的“本质是字典结构”的需求),可以在反序列化后手动做一次合并:
PayloadModel pm = JsonConvert.DeserializeObject<PayloadModel>(payload); Dictionary<string, float> mergedData = pm.Data .SelectMany(kvPair => kvPair) .ToDictionary(item => item.Key, item => item.Value);
方案2:自定义转换器直接反序列化为单个字典
如果你希望反序列化后直接得到单个字典而不是字典数组,可以自定义一个Json转换器实现数组到单字典的转换,这种方式需要在反序列化时传入转换器配置,模型定义可以调整为:
public class PayloadModel { public DateTime Timestamp { get; set; } [JsonConverter(typeof(ArrayToDictionaryConverter))] public Dictionary<string, float> Data { get; set; } }
注:ArrayToDictionaryConverter需要自行实现,逻辑是读取数组中的每个对象,把对象的键值对逐个写入目标字典即可。
内容的提问来源于stack exchange,提问作者James Lu
相关产品推荐
相关产品推荐

