16

I am using Swagger with Scala to document my REST API. I want to enable bulk operations for POST, PUT and DELETE and want the same route to accept either a single object or a collection of objects as body content.

Is there a way to tell Swagger that a param is either a list of values of type A or a single value of type A?

Something like varargs for REST.

Helen
  • 87,344
  • 17
  • 243
  • 314
bennidi
  • 2,092
  • 21
  • 27

3 Answers3

21

Is there a way to tell Swagger that a param is either a list of values of type A or a single value of type A?

This depends on whether you use OpenAPI 3.0 or OpenAPI (Swagger) 2.0.

OpenAPI uses an extended subset of JSON Schema to describe body payloads. JSON Schema provides the oneOf and anyOf keywords to define multiple possible schemas for an instance. However, different versions of OpenAPI support different sets of JSON Schema keywords.

OpenAPI 3.0 supports oneOf and anyOf, so you can describe such an object or array of object as follows:

openapi: 3.0.0
...

components:
  schemas:
    A:
      type: object
    Body:
      oneOf:
        - $ref: '#/components/schemas/A'
        - type: array
          items:
            $ref: '#/components/schemas/A'

In the example above, Body can be either object A or an array of objects A.

OpenAPI (Swagger) 2.0 does not support oneOf and anyOf. The most you can do is use a typeless schema:

swagger: '2.0'
...

definitions:
  A:
    type: object
  # Note that Body does not have a "type"
  Body:
    description: Can be object `A` or an array of `A`

This means the Body can be anything - an object (any object!), an array (containing any items!), also a primitive (string, number, etc.). There is no way to define the exact Body structure in this case. You can only describe this verbally in the description.

You'll need to use OpenAPI 3.0 to define your exact scenario.

Helen
  • 87,344
  • 17
  • 243
  • 314
Mohsen
  • 64,437
  • 34
  • 159
  • 186
  • 1
    Thanks for digging that up. It is a recognized drawback that hopefully will receive some attention in the future as it does hinder proper documentation of existing APIs like GeoJSON. This link adds to the discussion: https://github.com/swagger-api/swagger-spec/issues/57 I think for now I will just go with properly documenting the "List or single object" style in words. – bennidi Sep 09 '15 at 08:51
4

I don't know if it's possible to annotate your API like that with Swagger. But my suggestion is to simplify/unify your API. If you think about it, if you're going to support bulk (meaning an array of objects) then there's no reason to have a special treatment of a single object. You should just change the API to always take an array and if someone wants to do a single object then thats just the case of a list with a single element object :: Nil.

LuxuryMode
  • 33,401
  • 34
  • 117
  • 188
0

If you want to send object, just remove @OA\Items()

 *   @OA\RequestBody(
 *      required=true,
 *      @OA\JsonContent(
 *         ref="#/components/schemas/Brand"
 *      )
 *   ),
vantungit
  • 1
  • 1