Search code examples
angularswaggerswagger-codegenspringdoc

Swagger-ui flattens object in query params, but the generated angular client doesn't


I have the folloging Rest function in my spring boot application

@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);
}

and i use springdoc to generate openapi3 yaml

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

the generated yaml looks like that

generated yaml

then i generate a angular client

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

the generated client looks like the following

/**
 * 
 * 
 * @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
        }
    );
}

when i use the generated serve it makes requests like that:

wrong request

But when i use the swagger UI it works correct

correct with swagger ui

Why dies swagger-ui make correct requests but the generated angular-client doesn't?


Solution

  • This is an issue with the typescript-angular generator:

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

    A Pull Request has been created to fix this issue, I advise you to watch it:

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

    In the meantime you can try to solve the issue similarly to the @PageableAsQueryParam annotation available in springdoc-openapi-data-rest. That is, you can use @Parameters on your Spring controller method and @Parameter(hidden = true) on the method parameter itself to redefine the documentation manually.

    It sucks, but it's the best solution until the Pull Request goes through.

    In case of the method you wrote, the fix would be fairly simple, just add @PageableAsQueryParam and @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);
    }