Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Allow swagger query param to be array of strings or integers

In building a rest api using swagger2 (openAPI), I want to allow a query param station_id to support the following:

  • ?station_id=23 (returns station 23)
  • ?station_id=23,45 (returns stations 23 and 45)
  • ?station_id=[3:14] (returns stations 3 through 14)
  • ?station_id=100% (%s act as wildcards so returns things like 1001, 10049, etc..)

I use the following swagger definition (an array of strings) as an attempt to accomplish this:

parameters:
  - name: station_id
    in: query
    description: filter stations by station_id
    required: false
    type: array
    items:
      type: string

With this definition all of the previous examples work except ?station_id=23 as swagger validation fails with the following message:

{
  "message": "Validation errors",
  "errors": [
    {
      "code": "INVALID_REQUEST_PARAMETER",
      "errors": [
        {
          "code": "INVALID_TYPE",
          "params": [
            "array",
            "integer"
          ],
          "message": "Expected type array but found type integer",
          "path": [],
          "description": "filter stations by station_id"
        }
      ],
      "in": "query",
      "message": "Invalid parameter (station_id): Value failed JSON Schema validation",
      "name": "station_id",
      "path": [
        "paths",
        "/stations",
        "get",
        "parameters",
        "0"
      ]
    }
  ]
}

note that if I quote the station_id like ?station_id='23' validation passes and I get a correct response. But I'd really prefer not to have to use quotes. Something like a union type would help solve this, but as far as I can tell they aren't supported.

I also have another endpoint /stations/{id} that can handle the case of a single id, but still have many other (non primary key) numerical fields that I want to filter on in the way specified above. For instance station_latitude.

Any ideas to a work around - maybe I can use pattern (regex) somehow? If there is no workaround in the swagger definition is there a way to tweak or bypass the validator? This is a nodejs project using swagger-node I've upgraded the version of swagger-express-mw to 0.7.0.

like image 885
apricity Avatar asked Dec 21 '16 21:12

apricity


1 Answers

I think what you'd need is the anyOf or oneOf keyword similar to the one provided by JSON Schema so that you could define the type of your station_id parameter to be either a number or a string. anyOf and oneOf are supported in OpenAPI 3.0 but not in 2.0. An OpenAPI 3.0 definition would look like this:

openapi: 3.0.0
...
paths:
  /something:
    get:
      parameters:
        - in: query
          name: station_id
          required: true
          explode: false
          schema:
            oneOf:
              - type: integer # Optional? Array is supposed to cover the use case with a single number
                example: 23
              - type: array
                items:
                  type: integer
                minItems: 1
                example: [23, 45]
              - type: string
                oneOf:
                  - pattern: '^\[\d+:\d+]$'
                  - pattern: '^\d+%$'
                # or using a single pattern
                # pattern: '^(\[\d+:\d+])|(\d+%)$'
                example: '[3:14]'


As an alternative, perhaps you could add sortBy, skip, and limit parameters to allow you to keep the type uniform. For example: ?sortBy=station_id&skip=10&limit=10 would retrieve only stations 10 - 20.

like image 150
Brian Parry Avatar answered Oct 07 '22 16:10

Brian Parry