当前位置: 首页 > 知识库问答 >
问题:

SpringDoc生成具有多种媒体类型的OpenApi规范

劳烨
2023-03-14

在我的Spring项目中,我使用Springdoc生成OpenApiSpecification文档。我用这些注释创建了我的Api。我想用不同的mediatype拥有相同的endpointurl来处理不同对象的POST。

@Validated
@Tag(name = "Calendar", description = "Api for Calendar resource")
public interface CalendarApi {


    @Operation(summary = "Add an appointment to the calendar", description = "Add an appointment to the calendar", tags = {"appointment"})
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "Successful operation", content = @Content(mediaType = "application/json+widget", schema = @Schema(implementation = AppointmentWidgetDto.class))),
            @ApiResponse(responseCode = "400", description = "Invalid input")
    })
    @PostMapping(value = "/appointments", consumes = "application/json+widget")
    ResponseEntity<Appointment> saveFromWidget(@Parameter(description = "The new appointment to save", required = true) @Valid @RequestBody AppointmentWidgetDto appointmentDto);

    @Operation(summary = "Add an appointment to the calendar", description = "Add an appointment to the calendar", tags = {"appointment"})
    @ApiResponses(value = {
            @ApiResponse(responseCode = "201", description = "Successful operation", content = @Content(mediaType = "application/json", schema = @Schema(implementation = Appointment.class))),
            @ApiResponse(responseCode = "400", description = "Invalid input")
    })
    @PostMapping(value = "/appointments", consumes = MediaType.APPLICATION_JSON_VALUE)
    ResponseEntity<Appointment> save(@Parameter(description = "The new appointment to save", required = true) @Valid @RequestBody Appointment appointmentDto);

}

生成的开放式Api规范文档为:

  /api/v1/appointments:
    post:
      tags:
        - Calendar
      summary: Add an appointment to the calendar
      description: Add an appointment to the calendar
      operationId: save_1
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Appointment'
          application/json+widget:
            schema:
              $ref: '#/components/schemas/AppointmentWidgetDto'
        required: true
      responses:
        '201':
          description: Successful operation
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Appointment'
        '400':
          description: Invalid input
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Appointment'

我有几个问题:

>

  • 终结点名称没有意义(保存\u 1)

    当我使用OpenAPI生成器根据此规范生成Angular客户端时,我收到一些警告,这些警告会阻止生成这两种方法。

    [警告]在OAS'内容'部分中找到多个模式,仅返回第一个(应用程序/json)[警告]找到多个媒体类型,仅使用第一个

    我知道有这个问题打开(https://github.com/OpenAPITools/openapi-generator/issues/3990)。有没有办法允许在同一个endpointurl中发布两个不同的机构,并使用OpenApi生成器为不同的语言/平台创建客户端?

    ====更新=======

    这是约会WidgetDTO:

    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    public class AppointmentWidgetDto implements Serializable {
        @NotNull(message = "{appointment.store.missing}")
        @JsonDeserialize(using = StoreUriDeserializer.class)
        private Store store;
    
        @NotNull(message = "{appointment.title.missing}")
        @Size(max = 255)
        private String title;
    
        @Lob
        @Size(max = 1024)
        private String description;
    
        @Size(max = 50)
        private String type;
    
        @Size(max = 50)
        private String icon;
    
        @NotNull(message = "{appointment.startdate.missing}")
        private Instant startDate;
    
        @NotNull(message = "{appointment.enddate.missing}")
        private Instant endDate;
    
        @JsonDeserialize(using = ContactUriDeserializer.class)
        private Contact contact;
    
        @NotBlank(message = "{appointment.contactname.missing}")
        private String contactName;
    
        @NotBlank(message = "{appointment.email.missing}")
        @Email
        private String contactEmail;
    
        @NotBlank(message = "{appointment.phone.missing}")
        @PhoneNumber
        private String contactPhone;
    
    }
    

    这是预约:

    @ScriptAssert(lang = "javascript", script = "_.startDate.isBefore(_.endDate)", alias = "_", reportOn = "endDate", message = "{appointment.invalid.end.date}")
    @Getter
    @Setter
    @NoArgsConstructor
    @AllArgsConstructor
    @SuperBuilder
    public class Appointment extends AbstractEntity {
    
    
        @NotNull(message = "{appointment.store.missing}")
        @JsonDeserialize(using = StoreUriDeserializer.class)
        @ManyToOne(fetch = FetchType.LAZY, optional = false)
        @JoinColumn(name = "store_id", updatable = false)
        private Store store;
    
        @NotNull
        @Size(max = 255)
        @Column(nullable = false, length = 255)
        private String title;
    
        @Lob
        @Size(max = 1024)
        @Column(length = 1024)
        private String description;
    
        @Size(max = 30)
        @Column(length = 30)
        private String color;
    
        @Size(max = 50)
        @Column(length = 50)
        private String type;
    
        @Size(max = 50)
        @Column(length = 50)
        private String icon;
    
        @Size(max = 255)
        @Column(length = 255)
        private String location;
    
        @NotNull
        @Column(nullable = false)
        private Instant startDate;
    
        @NotNull
        @Column(nullable = false)
        private Instant endDate;
    
        @Builder.Default
        @NotNull
        @Column(nullable = false, columnDefinition = "BIT DEFAULT 0")
        private boolean allDay = false;
    
    
        @JoinColumn(name = "contact_id")
        @JsonDeserialize(using = ContactUriDeserializer.class)
        @ManyToOne(fetch = FetchType.LAZY)
        private Contact contact;
    
        private String contactName;
    
        @Email
        private String contactEmail;
    
        @PhoneNumber
        private String contactPhone;
    
       
        @JoinColumn(name = "agent_id")
        @JsonDeserialize(using = AgentUriDeserializer.class)
        @ManyToOne(fetch = FetchType.LAZY)
        private Agent agent;
    
       
        private String agentName;
    
        @Builder.Default
        @JsonProperty(access = JsonProperty.Access.READ_ONLY)
        @NotNull
        @Column(nullable = false)
        @Enumerated(EnumType.STRING)
        private AppointmentStatus status = AppointmentStatus.VALID;
    
  • 共有1个答案

    谭锐藻
    2023-03-14

    使用OpenAPI3,不能对同一路径执行多个操作。

    您将只有一个endpoint和一个OpenAPI描述。

    您可以做的是在其中一个方法的顶部定义@操作注释,在其中您可以添加所有其他方法的合并OpenAPI描述的OpenAPI留档,并添加@Hidden注释在其他人身上。

    或者,您可以定义两个不同的组:对于使用标题匹配过滤的每个组,选择groupedepanpiBean的headersToMatch

     类似资料:
    • 我有一个Spring Boot(kotlin)项目,我使用springdoc openapi生成openapi 3规范。我的数据模型如下所示: 还有一个简单的控制器,如下所示: 生成的yaml为: 这里的问题是我的控制器可以返回或,这在返回类型中指定。我期望生成的模式是: 有没有办法做到这一点?

    • 我正在从swagger(Open API 2)转向springdoc(Open API 3),但今天在某些情况下,我使用swagger-codemen-maven-plugin从yaml生成代码(用于客户端和提供商),遵循合同优先策略。下面是配置示例: 使用springdoc openapi maven插件生成代码有没有等效的选项?

    • OpenAPI3.0规范规定,没有任何类型的模式将匹配任何数据类型。 没有类型的模式匹配任何数据类型--数字、字符串、对象等等。 因此,对此进行建模的正确方法是下面的Swagger定义,其中没有属性: 但是,每个开放问题Swagger-core#3834,Java值都映射到OpenAPI类型,而不是任意类型。如上所述,这意味着这样的API返回或接受不是OpenAPI的类型是不正确的,例如、、等。

    • 我正在用OpenAPI生成器maven插件(版本为5.4.0)生成OpenAPI合同的源代码。 我正在使用java生成器和webclient库。 我有一个endpoint响应或: 问题是插件只是考虑第一个媒体类型(按声明顺序)来生成相应的java返回类型。 在上面的例子中,我必须处理字节[]。 如果我首先反转媒体类型(

    • **代码:(类名已重命名)** 两个版本中的CheeseDTO YAML: 使用springdoc-openapi-ui 1.3.9,我的yaml是这样生成的: 昂首阔步3注释: OpenAPi生成器maven插件 有没有办法用springdoc-openapi-ui>1.4.0生成?我必须更改我的大摇大摆的注释或更改我的java生成器吗?

    • 我使用的是默认配置,但由于某种原因,我一直收到以下错误: 任务“Generate OpenApidocs”执行失败。无法连接到http://localhost:8080/v3/api-文档等待了30秒 似乎由于某种原因,它没有设置服务器。我该怎么修好它?