C# 使用 Newtonsoft.Json 结合 Dictionary/List 创建无硬编码属性名的 DTO
动态键硬编码消除方案
核心思路
针对StorageData类下无固定枚举值的数字动态键,直接复用你已经验证可用的Dictionary承接逻辑,不需要硬编码"1""2"这类属性名,也不需要通过多JsonProperty特性做匹配。
原实现待优化点
当前StorageData类中硬编码的两个属性存在明显维护成本:
[JsonProperty(PropertyName = "2")] public DataInfo DataDetails2 { get; set; } [JsonProperty(PropertyName = "1")] public DataInfo DataDetails { get; set; }
- 后续JSON结构新增"3""4"等数字键时,必须手动新增属性加JsonProperty特性,扩展性极差
- 尝试通过
JsonPropertyTagNames = new Object[]{"1","2"}给单个属性绑定多个键名的写法不生效,是因为Newtonsoft.Json本身不支持单个CLR属性匹配多个动态键名,这类场景必须用字典结构承接。
修正后的实现逻辑
直接将StorageData类中的两个硬编码属性替换为字典结构,Newtonsoft.Json会自动把类结构中没有对应静态属性的所有键值对,映射到该字典属性中,和外层data字段的反序列化逻辑完全一致:
public class StorageData { /// <summary> /// 自动收集所有数字格式的动态键值对 /// 键为JSON中的数字字符串("1"/"2"/"3"...),值为对应DataInfo实例 /// </summary> public Dictionary<string, DataInfo> DataDetailsCollection { get; set; } = new(); }
注意:该字典属性不需要指定固定的JsonProperty名称,Newtonsoft.Json会自动扫描所有未匹配到静态属性的键做映射。
适配示例JSON的完整DTO代码
using System.Collections.Generic; using Newtonsoft.Json; namespace TestModels.Dto { /// <summary> /// 顶层响应结构 /// </summary> public class StorageData_v1 { /// <summary> /// API版本号 /// </summary> [JsonProperty(PropertyName = "apiVersion")] public string ApiVersion { get; set; } /// <summary> /// 按业务编号分类的存储数据集合,外层键为业务编号字符串 /// </summary> [JsonProperty(PropertyName = "data")] public Dictionary<string, StorageData> Data { get; set; } } /// <summary> /// 单个业务编号下的存储数据集合 /// </summary> public class StorageData { /// <summary> /// 按动态数字键收集的详情数据 /// </summary> public Dictionary<string, DataInfo> DataDetailsCollection { get; set; } = new(); } /// <summary> /// 单条数据详情 /// </summary> public class DataInfo { [JsonProperty(PropertyName = "juris")] public string Jurisdiction { get; set; } [JsonProperty(PropertyName = "entity")] public string Entity { get; set; } [JsonProperty(PropertyName = "instance")] public string Instance { get; set; } [JsonProperty(PropertyName = "calcJobId")] public string CalcJobId { get; set; } [JsonProperty(PropertyName = "formIndex")] public string FormIndex { get; set; } [JsonProperty(PropertyName = "ReturnId")] public string ReturnId { get; set; } [JsonProperty(PropertyName = "storage")] public Storage Storage { get; set; } } /// <summary> /// Base64存储数据集合 /// </summary> public class Storage { [JsonProperty(PropertyName = "$podRawBase64")] public string PodRawBase64 { get; set; } [JsonProperty(PropertyName = "$podDbkRawBase64")] public string PodDbkRawBase64 { get; set; } } }
验证结果
用提供的示例JSON测试反序列化时,可实现全字段无丢失映射:
- 顶层
apiVersion字段正常绑定到对应属性 data节点下的"738""463"键自动存入StorageData_v1.Data字典- 每个业务节点下的"1"键自动存入
StorageData.DataDetailsCollection字典,对应值正常反序列化为DataInfo实例 storage节点下的$podRawBase64、$podDbkRawBase64字段全部正常映射,不存在硬编码漏配问题
内容的提问来源于stack exchange,提问作者Mohan K
相关产品推荐
相关产品推荐

