Search code examples
springspring-bootswaggerswagger-codegen

Spring boot code generated from swaggerhub is not able to throw 400 on additional properties


I've logged in to swaggerhub and generated a sample inventory API which is part of their template. In codegen options selected spring as server. ticked on useBeanValidation checkbox. Generated the code, tested it. Validations are working properly as expected except only one thing. I don't want to allow any additional property on the POST payload.

NB: The openAPI specification doesn't have 'additionalProperties' flag specified. Which defaults it to 'false' in my understanding. I tried to explicitly specify the same too. but no luck. There is no exception thrown while I add an additionalProperty.

The OpenAPI specification

openapi: 3.0.0
servers:
  # Added by API Auto Mocking Plugin
  - description: SwaggerHub API Auto Mocking
    url: https://virtserver.swaggerhub.com/xxxx/apionopenApi3/1.0.0
info:
  description: This is a simple API
  version: "1.0.0"
  title: Simple Inventory API
  contact:
    email: you@your-company.com
  license:
    name: Apache 2.0
    url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
  - name: admins
    description: Secured Admin-only calls
  - name: developers
    description: Operations available to regular developers
paths:
  /inventory:
    get:
      tags:
        - developers
      summary: searches inventory
      operationId: searchInventory
      description: |
        By passing in the appropriate options, you can search for
        available inventory in the system
      parameters:
        - in: query
          name: searchString
          description: pass an optional search string for looking up inventory
          required: false
          schema:
            type: string
        - in: query
          name: skip
          description: number of records to skip for pagination
          schema:
            type: integer
            format: int32
            minimum: 0
        - in: query
          name: limit
          description: maximum number of records to return
          schema:
            type: integer
            format: int32
            minimum: 0
            maximum: 50
      responses:
        '200':
          description: search results matching criteria
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/InventoryItem'
        '400':
          description: bad input parameter
    post:
      tags:
        - admins
      summary: adds an inventory item
      operationId: addInventory
      description: Adds an item to the system
      responses:
        '201':
          description: item created
        '400':
          description: 'invalid input, object invalid'
        '409':
          description: an existing item already exists
      requestBody:
        content:
          application/json:
            schema:
              $ref: '#/components/schemas/InventoryItem'
        description: Inventory item to add
components:
  schemas:
    InventoryItem:
      type: object
      additionalProperties: False
      required:
        - id
        - name
        - manufacturer
        - releaseDate
      properties:
        id:
          type: string
          format: uuid
          example: d290f1ee-6c54-4b01-90e6-d701748f0851
        name:
          type: string
          example: Widget Adapter
        releaseDate:
          type: string
          format: date-time
          example: '2016-08-29T09:12:33.001Z'
        manufacturer:
          $ref: '#/components/schemas/Manufacturer'
    Manufacturer:
      required:
        - name
      properties:
        name:
          type: string
          example: ACME Corporation
        homePage:
          type: string
          format: url
          example: 'https://www.acme-corp.com'
        phone:
          type: string
          example: 408-867-5309
      type: object
      additionalProperties: False
        

Got 400 for this payload on post API.

{
    "id": "7f125802-7840-4ff0-8ddb-7c78c0948987",
    "name11111": "Widget Adapter",
    "releaseDate": "2016-08-29T09:12:33.001Z",
      "manufacturer": {
    "name": "ACME Corporation",
    "homePage": "",
    "phone": "408-867-5309"
        }
}

Expected 400 but didn't get on this payload on post

{
    "id": "7f125802-7840-4ff0-8ddb-7c78c0948983",
    "name": "Widget Adapter",
    "releaseDate": "2016-08-29T09:12:33.001Z",
      "manufacturer": {
    "name": "ACME Corporation",
    "homePage": "",
    "phone": "408-867-5309"
        },
    "newkey" : "newValue"

}

Can anybody pls help on this.. I want to completely disallow additional properties and throw a 400 on those requests..


Solution

  • The default for additionalProperties is actually True, not False.

    Adding false does not cause the swagger-codegen for Spring to actually disallow additional fields though, annoyingly enough. After a few hours of running in the wrong direction I found the solution:

    In application.properties spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true

    I had been having the same trouble and have tried to leverage filters but have had problems tying the models that are used in the automatic deserialization of @RequestBody to the servlet request and keeping the behavior consistent across model changes. Coming to that conclusion required writing quite a bit of unnecessary boilerplate and wasting a lot of time.

    I also tried to find a way to inject some behavior in the automatic use of the model or any model annotation that would change how the model automatically disregards additional fields without reporting the bad request. After exhausting the road of annotations I found the solution.