In Swagger Code gen, how do i specify required fields when creating a multipart file upload request?

Viewed 140

I'm using Java 11 and want to create an OpenAPI 3 request to upload multipart form data (a file and some other fields). I have this in my openApi yml file ...

  /myobjects/:
      post:
        tags:
          - my-objects
        summary: Adding my object
        operationId: addmyobject
        description: Creates a new my object.
        requestBody:
          content:
            multipart/form-data:
              schema:
                $ref: '#/components/schemas/MyObjectDTO'
          required: true
    ...
    MyObjectDTO:
      type: object
      properties:
        myId:
          type: integer
          format: int
          readOnly: true
        name:
          type: string
          maxLength: 100
          required: true
          example: myRequest
    ...
        myFile:
          type: string
          format: binary
      required:
        - name

I'm using the following configuraiton for Swagger code gen (Maven) in my pom.xml file ...

        <plugin>
            <groupId>io.swagger.codegen.v3</groupId>
            <artifactId>swagger-codegen-maven-plugin</artifactId>
            <version>3.0.17</version>
            ...
            <configuration>
                ...
                <generateApis>true</generateApis>
                <generateApiTests>false</generateApiTests>
                <generateModelTests>false</generateModelTests>
                <generateApiDocumentation>true</generateApiDocumentation>
                <generateModels>true</generateModels>
                <generateSupportingFiles>false</generateSupportingFiles>
                <languageSpecificPrimitives>true</languageSpecificPrimitives>
                <importMappings>
                    ...
                </importMappings>
                <configOptions>
                    <interfaceOnly>true</interfaceOnly>
                    <java8>false</java8>
                    <dateLibrary>java8</dateLibrary>
                    <sourceFolder>.</sourceFolder>
                    <throwsException>true</throwsException>
                    <useTags>true</useTags>
                </configOptions>
            </configuration>

The problem is when my API call generates, not only are all the fields from my DTO included, but they are all marked as required, despite the fact I have only specified that "name" is a required field in my DTO.

    @Operation(summary = "Adding my object", description = "Creates a new my object.", tags={ "my-objects" })
    @ApiResponses(value = { 
        @ApiResponse(responseCode = "201", description = "OK", content = @Content(schema = @Schema(implementation = ResponseData.class))) })
    @RequestMapping(value = "/myobjects/",
        produces = { "application/json" }, 
        consumes = { "multipart/form-data" },
        method = RequestMethod.POST)
    default ResponseEntity<ResponseData> addmyobject(
@Parameter(description = "", required=true) @RequestParam(value="myId", required=true) Integer myId
,
@Parameter(description = "", required=true) @RequestParam(value="name", required=true) String name
,
...
,
@Parameter(description = "file detail") @Valid @RequestPart("file") MultipartFile myFile
) throws Exception {

Is there a way to rewrite my yml, or configure code generation so that I can specify which fields are required and which I want included in my multi-part upload call?

2 Answers

My understanding of the OpenAPI 3 yml, is that the required: declaration for type: object should be declared before the properties: declaration, thus it determines which of the properties are required. Also removing required: true from the requestBody: configuration as the schema already defines what is required -

  /myobjects/:
      post:
        tags:
          - my-objects
        summary: Adding my object
        operationId: addmyobject
        description: Creates a new my object.
        requestBody:
          content:
            multipart/form-data:
              schema:
                $ref: '#/components/schemas/MyObjectDTO'
    ...
    MyObjectDTO:
      type: object
      required:
        - name
      properties:
        myId:
          type: integer
          format: int
          readOnly: true
        name:
          type: string
          maxLength: 100
          required: true
          example: myRequest
    ...
        myFile:
          type: string
          format: binary

I had a similar issue with swagger codegen. Looks indeed like a bug.

I fixed it by overriding the mustache file formParams.mustache.

You can let the codegen plugin override the default mustache files by putting your own file(s) in a folder on your classpath (like src/main/resources/mustache) and configure it in your pom by adding: <templateDirectory>${project.basedir}/src/main/resources/mustache</templateDirectory> to the <configuration> of the plugin.

The content of my formParams.mustache is:

{{#isFormParam}}{{^isBinary}}{{^useOas2}}@Parameter(in = ParameterIn.DEFAULT, description = "{{{description}}}"{{#required}}, required=true{{/required}},schema=@Schema({{#allowableValues}}{{> allowableValues }}{{/allowableValues}}{{#defaultValue}}{{#allowableValues}},{{/allowableValues}} defaultValue="{{{defaultValue}}}"{{/defaultValue}})){{/useOas2}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestParam(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}})  {{{dataType}}} {{paramName}}{{/isBinary}}{{#isBinary}}{{#useOas2}}@ApiParam(value = "file detail"){{/useOas2}}{{^useOas2}}@Parameter(description = "file detail"){{/useOas2}} {{#useBeanValidation}}@Valid{{/useBeanValidation}} @RequestPart(value="{{baseName}}"{{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}}) MultipartFile {{baseName}}{{/isBinary}}{{/isFormParam}}

As I can remember, the last {{#required}}, required=true{{/required}}{{^required}}, required=false{{/required}} part did the trick for me.

Related