Request Body

This OpenAPI describes an endpoint with requestBody:

openapi: 3.0.2
info:
  title: request body
  version: 1.0.0

paths:
  /book:
    post:
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/Book'
        required: true
      responses:
        '201':
          description: created book
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/Book'

components:
  schemas:
    Book:
      type: object
      properties:
        isbn:
          type: string
        title:
          type: string

that the processor will convert into the interface:

package generated.api;

import generated.model.Book;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;

public interface Api {

    @PostMapping(path = "/book", consumes = {"application/json"}, produces = {"application/json"})
    ResponseEntity<Book> postBook(@RequestBody Book body);

}

and a Book pojo.

multipart/form-data

For file uploads, where the content of the requestBody is multipart/form-data, the resulting code looks a bit different and requires a specific type mapping.

The file upload in OpenAPI is described like this:

/file-upload:
  summary: upload a file
  post:
    requestBody:
      content:
        multipart/form-data:
          schema:
            type: object
            properties:
              file:
                type: string
                format: binary

The schema must be of type object defining a property for each part in the multipart body.

Instead of generating a @RequestBody parameter for the object schema the processor creates a parameter for each property of the object annotated with @RequestParam:

package generated.api;

import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

public interface Api {

    @PostMapping(path = "/file-upload")
    ResponseEntity<Void> postFileUpload(@RequestParam(name = "file") MultipartFile file);

}

Note that the file property (type string format binary) is mapped to Springs MultipartFile type.

The processor does not have a default mapping for the binary format so to get the code above we have to configure it in the type mapping yaml:

map:
  paths:
    /file-upload:
      types:
        - type: string:binary => org.springframework.web.multipart.MultipartFile

To upload multiple files we can define the body object with an array property:

type: object
properties:
  files:
    type: array
    items:
      type: string
      format: binary

to get the following code:

@PostMapping(path = "/file-upload")
ResponseEntity<Void> postFileUpload(@RequestParam(name = "files") MultipartFile[] files);

multi-part encoding

since 2021.4

the parsing step extracts the encoding/contentType of a multipart content. This allows a processor to consider the encoding content type when selecting the annotation for the part.

the Spring processor uses this to select between @RequestPart and @RequestParam annotation. If an encoding/contentType is available it will use @RequestPart, if no encoding/contentType is available it will use @RequestParam.

openapi: 3.0.2
info:
  title: params-request-body-multipart
  version: 1.0.0

paths:
  /multipart:
    post:
      requestBody:
        required: true
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                file:
                  type: string
                  format: binary
                json:
                  type: object
                  properties:
                    foo:
                      type: string
                    bar:
                      type: string
            encoding:
              file:
                contentType: application/octet-stream
              json:
                contentType: application/json
      responses:
        '204':
          description: empty