如何创建DTO对象解析未知嵌套层级的多层JSON数据
方案选型建议
你可以根据自己对settings字段的实际使用场景,从以下几种方案里选最适配的:
1. 用JObject(或对应语言的动态JSON对象类型)
适用场景:需要频繁读写settings内部的任意属性,不需要编译期强类型校验的场景。
- 优势:
- 不需要提前定义嵌套结构,反序列化后可以直接访问任意层级的属性、数组元素,比如C#中直接通过
settings["exampleThree"]["subexampleOne"]即可取值,修改也很方便 - 原生支持序列化/反序列化,不需要自行处理JSON转义、格式校验逻辑
- 不需要提前定义嵌套结构,反序列化后可以直接访问任意层级的属性、数组元素,比如C#中直接通过
- 劣势:
- 没有编译期类型检查,字段名拼写错误、类型转换错误只能在运行时发现
- 性能略低于强类型DTO,但常规API调用场景基本感知不到差异
2. 直接用string存储原始JSON
适用场景:仅需要透传settings字段,不需要读写内部属性的场景,比如拿到响应后直接将settings存入数据库、或者转发给其他下游接口。
- 优势:
- 完全不依赖
settings的结构,反序列化/序列化零成本,不会出现解析过程丢失字段、修改格式的问题 - 存储、透传都不需要额外处理
- 完全不依赖
- 劣势:
- 只要需要读写内部属性,每次都要自行做序列化/反序列化,开发成本很高
3. 半强类型方案(优先推荐)
如果响应外层结构是固定的(比如示例中的name字段),只有settings结构不确定,可以先定义外层强类型DTO,settings字段根据需求选JObject/string即可,以C#为例:
public class ApiResponseDto { public string Name { get; set; } public JObject Settings { get; set; } }
如果有部分settings的子属性是确定会用到的,还可以封装扩展方法来统一处理取值逻辑,把运行时错误的风险控制在固定位置:
public static int? GetExampleTwo(this JObject settings) { if (settings.TryGetValue("exampleTwo", out var value) && value.Type == JTokenType.Integer) { return value.Value<int>(); } // 可以根据需求加默认值、打日志等逻辑 return null; }
额外可选方案(支持递归类型的语言适用)
如果你用的是TypeScript、Kotlin这类支持递归类型声明的语言,可以定义递归的通用结构来替代JObject,在不写死结构的前提下保留一定的类型校验能力,以TypeScript为例:
type NestedJsonValue = string | number | boolean | NestedJsonValue[] | { [key: string]: NestedJsonValue } interface ApiResponseDto { name: string settings: NestedJsonValue }
选择参考
- 仅透传不操作
settings:选string - 需要频繁读写
settings内部字段:选JObject/对应动态JSON类型 - 有固定子属性要读取:优先半强类型+扩展方法封装,降低出错概率
内容的提问来源于stack exchange,提问作者WymyslonyNick
相关产品推荐
相关产品推荐

