Swagger-ui 将查询参数中的对象展平,但生成的角度客户端不会

Posted

技术标签:

【中文标题】Swagger-ui 将查询参数中的对象展平,但生成的角度客户端不会【英文标题】:Swagger-ui flattens object in query params, but the generated angular client doesn't 【发布时间】:2020-04-13 02:47:30 【问题描述】:

我的 Spring Boot 应用程序中有以下 Rest 功能

@SecuredMaster
@GetMapping(path = "/mitarbeiter")
@Operation(security = @SecurityRequirement(name = "jwt"))
public Page<MitarbeiterListRow> getMitarbeiter(Pageable pageable, @RequestParam(defaultValue = "") String query) 
    return mitarbeiterRepository.findAllByUsernameContainingIgnoreCaseOrEmailContainingIgnoreCase(pageable, query, query);

我使用springdoc生成openapi3 yaml

// generate api docs
implementation 'org.springdoc:springdoc-openapi-ui:1.2.18'
implementation 'org.springdoc:springdoc-openapi-data-rest:1.2.18'

生成的 yaml 是这样的

然后我生成一个角度客户端

java -jar swagger-codegen-cli.jar generate -i http://localhost:8080/apidocs/v3/api-docs -l typescript-angular -o ../frontend/src/generated/swagger

生成的客户端如下所示

/**
 * 
 * 
 * @param pageable 
 * @param query 
 * @param observe set whether or not to return the data Observable as the body, response or events. defaults to returning the body.
 * @param reportProgress flag to report request and response progress.
 */
public getMitarbeiter(pageable: Pageable, query?: string, observe?: 'body', reportProgress?: boolean): Observable<PageMitarbeiterListRow>;
public getMitarbeiter(pageable: Pageable, query?: string, observe?: 'response', reportProgress?: boolean): Observable<HttpResponse<PageMitarbeiterListRow>>;
public getMitarbeiter(pageable: Pageable, query?: string, observe?: 'events', reportProgress?: boolean): Observable<HttpEvent<PageMitarbeiterListRow>>;
public getMitarbeiter(pageable: Pageable, query?: string, observe: any = 'body', reportProgress: boolean = false ): Observable<any> 

    if (pageable === null || pageable === undefined) 
        throw new Error('Required parameter pageable was null or undefined when calling getMitarbeiter.');
    


    let queryParameters = new HttpParams(encoder: new CustomHttpUrlEncodingCodec());
    if (pageable !== undefined && pageable !== null) 
        queryParameters = queryParameters.set('pageable', <any>pageable);
    
    if (query !== undefined && query !== null) 
        queryParameters = queryParameters.set('query', <any>query);
    

    let headers = this.defaultHeaders;

    // authentication (jwt) required
    if (this.configuration.accessToken) 
        const accessToken = typeof this.configuration.accessToken === 'function'
            ? this.configuration.accessToken()
            : this.configuration.accessToken;
        headers = headers.set('Authorization', 'Bearer ' + accessToken);
    
    // to determine the Accept header
    let httpHeaderAccepts: string[] = [
        '*/*'
    ];
    const httpHeaderAcceptSelected: string | undefined = this.configuration.selectHeaderAccept(httpHeaderAccepts);
    if (httpHeaderAcceptSelected != undefined) 
        headers = headers.set('Accept', httpHeaderAcceptSelected);
    

    // to determine the Content-Type header
    const consumes: string[] = [
    ];

    return this.httpClient.get<PageMitarbeiterListRow>(`$this.basePath/mitarbeiter`,
        
            params: queryParameters,
            withCredentials: this.configuration.withCredentials,
            headers: headers,
            observe: observe,
            reportProgress: reportProgress
        
    );

当我使用生成的服务时,它会发出这样的请求:

但是当我使用 swagger UI 时它可以正常工作

为什么 swagger-ui 会发出正确的请求,但生成的 angular-client 却没有?

【问题讨论】:

【参考方案1】:

这是 typescript-angular 生成器的问题:

https://github.com/OpenAPITools/openapi-generator/issues/4404

已经创建了一个拉取请求来解决这个问题,我建议你观看它:

https://github.com/OpenAPITools/openapi-generator/pull/4407

与此同时,您可以尝试类似于 springdoc-openapi-data-rest 中的 @PageableAsQueryParam 注释来解决问题。也就是说,您可以在 Spring 控制器方法上使用 @Parameters 并在方法参数本身上使用 @Parameter(hidden = true) 来手动重新定义文档。

这很糟糕,但在拉取请求通过之前,这是最好的解决方案。

如果是您编写的方法,修复将相当简单,只需添加@PageableAsQueryParam@Parameter(hidden = true)

@PageableAsQueryParam
@SecuredMaster
@GetMapping(path = "/mitarbeiter")
@Operation(security = @SecurityRequirement(name = "jwt"))
public Page<MitarbeiterListRow> getMitarbeiter(@Parameter(hidden = true) Pageable pageable, @RequestParam(defaultValue = "") String query) 
    return mitarbeiterRepository.findAllByUsernameContainingIgnoreCaseOrEmailContainingIgnoreCase(pageable, query, query);

【讨论】:

@PageableAsQueryParam 在1.2.18 版本中不可用,但1.2.29 似乎有它

以上是关于Swagger-ui 将查询参数中的对象展平,但生成的角度客户端不会的主要内容,如果未能解决你的问题,请参考以下文章

对表格多数组的环回响应/将对象的嵌套数组展平为线性数组

将 [FromQuery] 与复杂对象一起使用

AutoMapper - 试图将我的对象属性展平为字符串但出现错误

使用Springfox和Swagger-ui上传Multipart文件

您可以将文件展平到 Snowflake 中的外部表吗?

将带有数组的 json 结构展平为多个没有数组的平面对象