C#中如何实现属性结构动态可变的类以适配不确定结构的JSON数据
dynamic 方案的问题
使用dynamic处理动态属性结构时,编译期会跳过类型检查,你遇到的空引用提示是因为编译器无法确认properties、address、name是否存在、是否为null,所有成员访问的校验都会延迟到运行时,一旦字段缺失就会直接抛出运行时异常,调试成本和故障率都更高,除非完全不需要访问properties内部字段仅做序列化透传,否则不推荐用dynamic。
推荐实现方案
方案1:用JsonNode(.NET 6+ 优先选,基于System.Text.Json)
JsonNode是.NET官方提供的轻量级动态JSON操作类,兼顾动态访问的灵活性和类型安全性,序列化输出和原dynamic方案完全一致。
代码实现
using System.Text.Json.Nodes; public class Customer { public string name { get; set; } public JsonNode properties { get; set; } }
安全访问嵌套字段
// 字段不存在时返回null,不会抛出异常 string addressName = properties?["address"]?["name"]?.GetValue<string>(); // 也可以主动判断字段存在性再处理 if (properties.AsObject().TryGetPropertyValue("address", out var addressNode) && addressNode.AsObject().TryGetPropertyValue("name", out var nameNode)) { string validName = nameNode.GetValue<string>(); // 后续业务逻辑 }
序列化直接调用JsonSerializer.Serialize(customer)即可输出符合要求的JSON结构。
方案2:用JObject(适配Newtonsoft.Json场景)
如果你的项目仍在使用Newtonsoft.Json(Json.NET),可以用JObject替代dynamic:
代码实现
using Newtonsoft.Json.Linq; public class Customer { public string name { get; set; } public JObject properties { get; set; } }
安全访问嵌套字段
string addressName = properties?["address"]?["name"]?.Value<string>();
方案3:固定字段+动态字段混合场景用[JsonExtensionData]
如果properties存在部分必传的固定字段,其余字段为动态,可以结合强类型和扩展字段特性,兼顾强类型访问的便利性和动态结构兼容性:
代码实现
using System.Text.Json.Serialization; // 定义properties的固定字段 public class CustomerProperties { // 固定必传字段,可强类型访问 public string name { get; set; } // 所有未匹配的动态字段都会自动存入该字典,序列化时会直接展开到properties层级 [JsonExtensionData] public Dictionary<string, object> DynamicFields { get; set; } } public class Customer { public string name { get; set; } public CustomerProperties properties { get; set; } }
选型建议
- 仅需要透传动态JSON,不需要访问内部字段:可以继续用dynamic,注意做空引用判断即可
- 需要访问动态字段,项目基于.NET 6+:优先选JsonNode方案
- 项目仍依赖Newtonsoft.Json:选JObject方案
- properties有部分固定字段:选JsonExtensionData混合方案
内容的提问来源于stack exchange,提问作者Learn AspNet
相关产品推荐
相关产品推荐

