OpenAPITools / openapi-generator

OpenAPI Generator allows generation of API client libraries (SDK generation), server stubs, documentation and configuration automatically given an OpenAPI Spec (v2, v3)
https://openapi-generator.tech
Apache License 2.0
21.85k stars 6.59k forks source link

[REQ] Support for @SpringQueryMap in spring-cloud #9681

Open pohorelec opened 3 years ago

pohorelec commented 3 years ago

Could you please add support for @SpringQueryMap for @GetMapping if parameter is type of Object?

Support for:

generator: spring library: spring-cloud

Example:

ResponseEntity<List<Client>> findClients(@NotNull @SpringQueryMap @ApiParam(value = "Client filter object", required = true) @Valid ClientFilter filter);

Propsed solution:

Change JavaSpring/queryParams.mustache to

{{#isQueryParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} {{#isExplode}}{{#isDeepObject}}@org.springframework.cloud.openfeign.SpringQueryMap{{/isDeepObject}}{{/isExplode}}{{^isModel}} @RequestParam(value = {{#isMap}}""{{/isMap}}{{^isMap}}"{{baseName}}"{{/isMap}}{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{^isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}){{/isModel}}{{#isDate}} @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE){{/isDate}}{{#isDateTime}} @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME){{/isDateTime}} {{>optionalDataType}} {{paramName}}{{/isQueryParam}}

This code snippet adds support for serialize object as query parameters

{{#isExplode}}{{#isDeepObject}}@org.springframework.cloud.openfeign.SpringQueryMap{{/isDeepObject}}{{/isExplode}}

Thank you

mariodmpereira commented 1 year ago

Hey @pohorelec!

Have you found a solution/workaround for this problem?

Thanks.

Mário

pohorelec commented 1 year ago

Hi @mariodmpereira

We used ucstom mustache template for fiegn client genenration. Here is our solution:

  1. Create new directory src/main/resources/custom/spring_java_client
  2. Create new file queryParams.mustache under src/main/resources/custom/spring_java_client
  3. Paste following code to queryParams.mustache file:

{{#isQueryParam}}{{#useBeanValidation}}{{>beanValidationQueryParams}}{{/useBeanValidation}}@ApiParam(value = "{{{description}}}"{{#required}}, required = true{{/required}}{{#allowableValues}}, allowableValues = "{{#values}}{{{.}}}{{^-last}}, {{/-last}}{{#-last}}{{/-last}}{{/values}}"{{/allowableValues}}{{^isContainer}}{{#defaultValue}}, defaultValue = "{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}) {{#useBeanValidation}}@Valid{{/useBeanValidation}} {{#isExplode}}@org.springframework.cloud.openfeign.SpringQueryMap{{/isExplode}}{{^isModel}} @RequestParam(value = {{#isMap}}""{{/isMap}}{{^isMap}}"{{baseName}}"{{/isMap}}{{#required}}, required = true{{/required}}{{^required}}, required = false{{/required}}{{^isContainer}}{{#defaultValue}}, defaultValue="{{{defaultValue}}}"{{/defaultValue}}{{/isContainer}}){{/isModel}}{{#isDate}} @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE){{/isDate}}{{#isDateTime}} @org.springframework.format.annotation.DateTimeFormat(iso = org.springframework.format.annotation.DateTimeFormat.ISO.DATE_TIME){{/isDateTime}} {{>optionalDataType}} {{paramName}}{{/isQueryParam}}

This is link to original mustache file - https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/resources/JavaSpring/queryParams.mustache

Note: you can override any mustache plugin to your needs (not only queryParams). All you need to do is to ensure correct directory path of mustache template

The last thing you need to do is configure maven openapi plugin as follows:

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>${open-api-generator-maven-plugin.version}</version>
    <executions>
        <execution>
            <id>foo-api</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/../foo-endpoint/src/main/resources/api.yaml
                </inputSpec>
                <output>${project.build.directory}/generated-sources/swagger</output>
                <generatorName>spring</generatorName>
                <apiPackage>com.bar.foo.api</apiPackage>
                <modelPackage>com.bar.foo.api.model</modelPackage>
                <templateDirectory>${project.basedir}/src/main/resources/custom/spring_java_client</templateDirectory>
                <!-- for more config see - https://openapi-generator.tech/docs/generators/spring/ -->
                <configOptions>
                    <library>spring-cloud</library>
                    <interfaceOnly>true</interfaceOnly>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

Note: If you need to use this for various projects, you can move mustache file into java library and then just add dependency for plugin configuration as follows:

<plugin>
    <dependencies>
        <dependency>
            <groupId>com.baz.foo</groupId>
            <artifactId>openapi-templates</artifactId>
            <version>${openapi-templates.version}</version>
        </dependency>
    </dependencies>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>${open-api-generator-maven-plugin.version}</version>
    <executions>
        <execution>
            <id>foo-api</id>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>
                    ${project.basedir}/../foo-endpoint/src/main/resources/api.yaml
                </inputSpec>
                <output>${project.build.directory}/generated-sources/swagger</output>
                <generatorName>spring</generatorName>
                <apiPackage>com.bar.foo.api</apiPackage>
                <modelPackage>com.bar.foo.api.model</modelPackage>
                <templateResourcePath>custom/spring_java_endpoint</templateResourcePath>
                <!-- for more config see - https://openapi-generator.tech/docs/generators/spring/ -->
                <configOptions>
                    <library>spring-cloud</library>
                    <interfaceOnly>true</interfaceOnly>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

Then you have to use templateResourcePath instead of templateDirectory in configuration section of plugin