Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Define array of multiple models in Swagger 2.0

This is my first foray into Swagger so please be gentle.

I have the following definitions:

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          $ref: '#/definitions/Indicator'
  Indicator:
    type: object
    properties:
      type:
        type: string
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
  BBANDS:
    properties:
      type:
        type: string
        default: BBANDS
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
        properties:
          timeperiod:
            type: integer
            format: int32
            default: 5
          nbdevup:
            type: integer
            format: int32
            default: 2
          nbdevdn:
            type: integer
            format: int32
            default: 2
          matype:
            type: integer
            format: int32
            default: 0
  DEMA:
    properties:
      type:
        type: string
        default: DEMA
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
        properties:
          timeperiod:
            type: integer
            format: int32
            default: 5

So Payload has a property called indicator which is an array of Indicators. The BBANDS and DEMA are models which are of type Indicator (which I know doesn't translate to Swagger). What I'd like to do is define an array of the actual models with their defaults, in this case BBANDS and DEMA. Something like this:

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          - '#/definitions/BBANDS'
          - '#/definitions/DEMA'

or

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          - $ref '#/definitions/BBANDS'
          - $ref '#/definitions/DEMA'

Neither of which work of course. The reason is while the Indicator model describes an indicator correctly, different indicators can have a different parameter set.

Is there a way to essentially define a list of several models or perhaps map the BBANDS and DEMA models into Indicator?

Edit: Result of using @Helen's first suggestion in the Swagger Editor

enter image description here

like image 610
Jason Strimpel Avatar asked Dec 12 '16 07:12

Jason Strimpel


People also ask

How do you declare an array of strings in swagger?

YAML. Firstly, we start by specifying the array of strings in Swagger using YAML notation. In the schema section, we include type: array with items String.

How do you declare an empty array in swagger?

You can specify an empty array [] as an example for your array schema. This will override the default examples values generated by Swagger UI. Save this answer.


1 Answers

Swagger/OpenAPI 2.0 does not support multiple types for items, but there are a couple of ways to describe what you need.

Option 1 - Model Inheritance

As long as you have one field that is common between the models and can be used to distinguish between them, you can use model inheritance:

https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaDiscriminator https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#composition-and-inheritance-polymorphism

In your example, this property is type (type="BBANDS" or type="DEMA"). So you can:

  • Inherit the BBANDS and DEMA models from Indicator by using allOf.
  • Add discriminator: type to Indicator to indicate that the type property will be used to distinguish between the sub-models.
  • Define Payload as an array of Indicator. This way it can actually be an array of BBANDS or an array of DEMA.

definitions:
  Payload:
    type: object
    properties:
      indicators:
        type: array
        items:
          $ref: '#/definitions/Indicator'

  Indicator:
    type: object
    properties:
      type:
        type: string
        # Limit the possible values if needed
        #enum:
        #  - BBANDS
        #  - DEMA
      computeOn:
        type: array
        items:
          type: string
        default:
          - close

    # The "type" property will be used to distinguish between the sub-models.
    # The value of the "type" property MUST be the schema name, that is, "BBANDS" or "DEMA".
    # (Or in other words, the sub-model schema names must match possible values of "type".)
    discriminator: type
    required:
      - type

  BBANDS:
    allOf:
      - $ref: '#/definitions/Indicator'
      - type: object
        properties:
          parameters:
            type: object
            properties:
              timeperiod:
                type: integer
                format: int32
                default: 5
              nbdevup:
                type: integer
                format: int32
                default: 2
              nbdevdn:
                type: integer
                format: int32
                default: 2
              matype:
                type: integer
                format: int32
                default: 0
  DEMA:
    allOf:
      - $ref: '#/definitions/Indicator'
      - type: object
        properties:
          parameters:
            type: object
            properties:
              timeperiod:
                type: integer
                format: int32
                default: 5

Option 2 - Single Model

If all parameters are integer, you can have a single model Indicator with parameters defined as a hashmap. But in this case you lose the ability to define the exact parameters for specific indicator types.

definitions:
  Indicator:
    type: object
    properties:
      type:
        type: string
        enum:
          - BBANDS
          - DEMA
      computeOn:
        type: array
        items:
          type: string
        default:
          - close
      parameters:
        type: object
        properties:
          # This is a common parameter in both BBANDS and DEMA
          timeperiod:
            type: integer
            format: int32
            default: 5
        # This will match additional parameters "nbdevup", "nbdevdn", "matype" in BBANDS
        additionalProperties:
          type: integer
like image 91
Helen Avatar answered Oct 07 '22 00:10

Helen