如何为含自嵌套结构的对象编写FieldDescriptor及OpenAPI文档
解决递归嵌套对象的FieldDescriptor与OpenAPI定义问题
首先,我们来拆解你遇到的两个核心问题:递归结构的FieldDescriptor标注,以及payload未文档化的报错。
1. 先修正核心结构不匹配问题
你提供的报错payload里,myObject是一个数组,但你的OpenAPI定义里myObject是对象(type: object)——这是导致"未文档化"报错的直接原因!
如果你的API确实返回myObject作为数组,那需要调整OpenAPI定义:
components: schemas: myObject: type: object properties: values: type: array description: an array of 'STRING', 'BOOLEAN', 'NUMBER', or 'myObject' items: oneOf: - type: string - type: integer - type: boolean - $ref: '#/components/schemas/myObject' # 新增数组类型的定义 myObjectArray: type: array items: $ref: '#/components/schemas/myObject'
如果这只是笔误,实际myObject应该是对象,那修正payload为:
{ "myObject": { "values":[ { "values":[ "pasta" ] }, { "values":[ "pizza" ] }, { "values":[ "mandolino" ] } ] } }
2. 编写支持无限嵌套的递归FieldDescriptor
Java里直接创建递归的静态List<FieldDescriptor>会有初始化问题,我们可以用延迟加载的方式实现递归引用:
public static List<FieldDescriptor> getMyObjectDescriptor() { // 定义嵌套对象的字段描述,递归引用自身的描述符 FieldDescriptor nestedMyObject = fieldWithPath("values[]") .description("Can be a string, number, boolean, or nested myObject") .type(JsonFieldType.VARIES) .subFields(getMyObjectDescriptor()); return List.of( fieldWithPath("values") .type(JsonFieldType.ARRAY) .description("Array containing strings, numbers, booleans, or nested myObject instances") .optional() .subFields(List.of(nestedMyObject)) ); }
如果你使用的是SpringDoc这类支持Schema引用的库,也可以直接关联OpenAPI的递归Schema,更简洁:
public static List<FieldDescriptor> myObjectDescriptor = List.of( fieldWithPath("values") .type(JsonFieldType.ARRAY) .description("May be an array of 'STRING', 'BOOLEAN', 'NUMBER', or 'myObject'") .optional() .itemsSchemaRef("#/components/schemas/myObject") );
3. 简化版:不标注数组内部细节的解决方案
如果不想详细标注嵌套层级,至少要覆盖到嵌套对象的values字段,避免未文档化报错:
public static List<FieldDescriptor> myObjectDescriptor = List.of( fieldWithPath("values") .type(JsonFieldType.ARRAY) .description("May be an array of 'STRING', 'BOOLEAN', 'NUMBER', or 'myObject'") .optional(), // 覆盖嵌套对象的values字段,支持任意层级 fieldWithPath("values[].values") .type(JsonFieldType.ARRAY) .description("Nested values array in a myObject instance") .optional() );
关键补充:OpenAPI递归结构的正确写法
虽然你之前注释了oneOf,但要准确描述递归结构,oneOf是必须的(除非有特殊限制):
components: schemas: myObject: type: object properties: values: type: array description: An array of strings, numbers, booleans, or nested myObject instances items: oneOf: - type: string - type: integer - type: boolean - $ref: '#/components/schemas/myObject'
内容的提问来源于stack exchange,提问作者beegotsy
相关产品推荐
相关产品推荐

