Search code examples
api-designswagger-2.0

Have arrays within arrays in a Swagger responses


I am trying to define an API in Swagger where the result of a GET is an array of items for model MainModel each with an associated array of items from another model called AnotherModel. Something like this (which does not seem to be allowed):

responses:
    200:
      description: search results matching criteria
      schema:
        type: array
        items:
          $ref: '#/definitions/MainModel'
          type: array
          items: $ref: '#/definitions/AnotherModel'

Solution

  • First of all, OpenAPI Specification supports associative arrays / dictionaries with string keys only, such as:

    {
      "foo": 5,
      "bar": 2
    }
    

    but not C#'s Dictionary<int, string> where keys are int.

    An associative array is defined by using an object schema with the additionalProperties keyword specifying the type of array values. The key type is not mentioned because keys are always strings.

    type: object
    additionalProperties:
      type: <type of array values>
      # OR
      # $ref: '#/definitions/ValueModel'
    

    Similarly, an array of associative arrays can be defined as follows:

    type: array
    items:
      type: object
      additionalProperties:
        type: <type of values in associative array>
        # OR
        # $ref: '#/definitions/ValueModel'
    

    In your example, the values of associative array are of type AnotherModel. So an inline definition would look like:

          responses:
            200:
              description: search results matching criteria
              schema:
                type: array
                items:
                  type: object
                  additionalProperties:
                    $ref: '#/definitions/AnotherModel'
    
    definitions:
      AnotherModel:
        type: <whatever> # TODO
    

    Or if we introduce an intermediate MainModel that represents the associative array (as in your original example):

          responses:
            200:
              description: search results matching criteria
              schema:
                type: array
                items:
                  $ref: '#/definitions/MainModel'
    
    definitions:
      MainModel:  # Associative array of AnotherModel
        type: object
        additionalProperties:
          $ref: '#/definitions/AnotherModel'
      AnotherModel:
        type: <whatever> # TODO
    

    A couple of notes:

    • Each model referenced via $ref must be defined in the definitions section. So if you use $ref: '#/definitions/MainModel', your spec must include

        definitions:
          MainModel:
      
    • $ref works by replacing itself and all its sibling elements with the definition it is pointing at. That's why your original example is not valid:

        items:
          $ref: '#/definitions/MainModel'
          type: array
          items: $ref: '#/definitions/AnotherModel'
      

      Nested models can be either defined completely inline or referenced via $ref, but not both.