Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parameter of type "associative array" #380

Closed
yanjost opened this issue May 27, 2015 · 23 comments
Closed

Parameter of type "associative array" #380

yanjost opened this issue May 27, 2015 · 23 comments

Comments

@yanjost
Copy link

yanjost commented May 27, 2015

Let's use the "pet store" application as example

Imagine that you can send multiple "find" requests in one. For that, you pass an array of associative arrays, which contain a list of integers

Text version:

criteria[0][status]: 1
criteria[0][tags]: 2,3
criteria[1][status]: 2
criteria[1][tags]: 4,5
POST /find HTTP/1.1
Host: petstore.com
Content-Type: application/x-www-form-urlencoded

criteria%5B0%5D%5Bstatus%5D=1&criteria%5B0%5D%5Btags%5D=2%2C3&criteria%5B1%5D%5Bstatus%5D=2&criteria%5B1%5D%5Btags%5D=4%2C5

How would you define that ?

I suggest the following syntax addition : adding a new property "indexType" to give the type of the keys in an array (default: integer, 0-based)

Example definition using this syntax

swagger: '2.0'
info:
  version: '1.0.0'
  title: Swagger Petstore (Simple)
  description: A sample API that uses a petstore as an example to demonstrate features in the swagger-2.0 specification
  termsOfService: http://helloreverb.com/terms/
  contact:
    name: Swagger API team
    email: foo@example.com
    url: http://swagger.io
  license:
    name: MIT
    url: http://opensource.org/licenses/MIT
host: petstore.swagger.wordnik.com
basePath: /api
schemes:
  - http
consumes:
  - application/json
produces:
  - application/json
paths:
  /pets/find:
    get:
      description: Returns multiple search query results at the same time
      operationId: findPets
      produces:
        - application/json
        - application/xml
        - text/xml
        - text/html
      parameters:
        - name: criteria
          in: query
          description: search criteria
          required: true
          type: array
          items:
            type: array
            indexType: searchCriteria
            uniqueItems: true
            items:
              type: array
              items:
                type: integer
          collectionFormat: csv
      responses:
        '200':
          description: pet response
          schema:
            type: array
            items:
              type: array
              $ref: '#/definitions/pet'
        default:
          description: unexpected error
          schema:
            $ref: '#/definitions/errorModel'
definitions:
  searchCriteria:
    type: string
    enum:
    - tags
    - status
  pet:
    required:
      - id
      - name
    properties:
      id:
        type: integer
        format: int64
      name:
        type: string
      tag:
        type: string
  errorModel:
    required:
      - code
      - message
    properties:
      code:
        type: integer
        format: int32
      message:
        type: string
@rkyoku
Copy link

rkyoku commented Aug 25, 2015

Hi there,

Any news on that? Associative arrays are all over the place in APIs (at least then ones I worked/work on)

I suggest using the simple "keys" parameter:

name: pop
description: population by country
type: array
keys:
    type: string
    description: country code (2 characters)
items:
    type: integer
    description: population (in thousands)

Do you think it is feasible to add it? For now I am using "x-keys" with the same format, but it won't display in the generated documentation (unless I'm mistaken)

@webron
Copy link
Member

webron commented Aug 25, 2015

Can you reference any public standard that defines such a format?

Can you reference any public common API that exposes that format?

Right now, the usage of this format seems esoteric.

@rkyoku
Copy link

rkyoku commented Aug 25, 2015

On the contrary, can you firmly state that absolutely no API would have any use for associative arrays?

Just one example (because I do not know each and every API out there):

https://apidocs.mailchimp.com/api/2.0/lists/webhooks.php

Here the "actions" is a definite list that keeps growing. What if one day you could have any number of "actions" here, or even custom actions? The solution you propose would be to change the format of returned data so that it is not an associative array anymore, but an indexed array instead. Which would break existing code calling that API.

Instead, having an associative array here (which is nothing more than a generic object), would allow for a seamless transition.

Just my 2 cents. And authorizing a new property "keys" for "type: array" data does not seem that much esoteric to me. As long as something is constant (here it would be the items/values), it maskes sense to allow its declaration imho.

Someone else asked for it here : #289

The given example is a list of data by country, with the country 2 letters code being the key (this is the example I quoted in my comment).

@webron
Copy link
Member

webron commented Aug 25, 2015

I can't say that, but I can say that we don't aim to accommodate for any kind of API out there, so just because there is a way to do it, that's not reason enough for us to support it.

As for the mailchimp API, that doesn't look anything like what the OP requested. It's just an array of objects which is already supported by the spec (though please correct me if I'm wrong).

As for defining a generic object, you can do that today too. It's ill-advised, and we don't encourage it, but you can. That's pretty much saying you don't want to document your API (in most cases, not all).

@ePaul
Copy link
Contributor

ePaul commented Sep 14, 2015

JSON Schema has something like this:

name: pop
description: population by country
type: object
patternProperties:
  '[A-Z]{2}':
    type: integer
    description: the population of the country indicated by the property name.

This syntax is not imported by Swagger, though. I guess if this would be supported, that would be the way to go.

@rkyoku
Copy link

rkyoku commented Sep 14, 2015

That's indeed what I ended up using after some research. If Swagger does
not support it already, I'm confident they will soon!

Thank you Paulo!

Le lun. 14 sept. 2015 à 16:50, Paŭlo Ebermann notifications@github.com a
écrit :

JSON Schema has something like this:

name: popdescription: population by countrytype: objectpatternProperties:
'[A-Z]{2}':
type: integer
description: the population of the country indicated by the property name.

This syntax is not imported by Swagger, though. I guess if this would be
supported, that would be the way to go.


Reply to this email directly or view it on GitHub
#380 (comment)
.

@peterhadlaw
Copy link

The JSON API Spec actually has this for it's "field" query param.
/?fields[{TYPE}]={TYPE_FIELD1},{TYPE_FIELD2}&fields[{ANOTHER_TYPE}].....

http://jsonapi.org/format/#fetching-sparse-fieldsets

@unleashed
Copy link

Rack is a quite common piece of software used in frameworks like Rails and Sinatra that has long parsed query parameters like array[]=1&array[]=2&array[]=3 into an array and hash[key]=value1&hash[another_key]=value2 into dict/hash types. Even then some parameters like hash[key_containing_array][] parse into a hash which contains an array.

This has been like this for a very long time. See https://github.com/rack/rack/blob/1.6.4/lib/rack/utils.rb#L111-L168 for their code.

I'd say there are tons of use cases out there like these where key and another_key are totally free-form. Probably less of those where hash is also completely free-form, but still existing.

@mish15
Copy link

mish15 commented Jan 18, 2016

👍

1 similar comment
@SimplicityGuy
Copy link

+1

@jharmn
Copy link
Contributor

jharmn commented Feb 12, 2016

Link to parent #565

@okigan
Copy link

okigan commented May 4, 2016

+1

standard feature in all rails applications [1], also seems the only reasonable way to pass 1 or more! nested maps on through query strings. ie for essential for a GET request.

Also see "What Does normalize_params Do?" section for consice description how parsing is done.

[1] http://guides.rubyonrails.org/action_controller_overview.html#hash-and-array-parameters

@hskrasek
Copy link

hskrasek commented Aug 18, 2016

Does anyone have a solution for this in the meantime? Obviously can't leave an endpoint undocumented.

I'm assuming something like this work work in the meantime?

{
            "name": "filters[tms_id]",
            "in": "query",
            "required": false,
            "type": "array",
            "items": {
              "type": "string"
            },
            "collectionFormat": "multi"
          }

@davidwhthomas
Copy link

davidwhthomas commented Sep 30, 2016

I'm having a similar issue with array parameters. Does anyone have any suggestions how to describe an associative array in the query request such as:
http://example.com/api/rest/content?type=search&id=test&options[start]=20&options[limit]=10

I've come close with the following:

    - name: options
      in: query
      description: Additional options.
      required: false
      type: array
      items:
        type: string
      collectionFormat: multi

But that comes out as: http://example.com/api/rest/content?type=search&id=test&options=20&options=10

@jeremycohensolal
Copy link

jeremycohensolal commented Nov 18, 2016

Hello,

stripe uses this for search by date API

something like

GET /charges?date[gte]=2016-01-01&date[lte]=2016-01-02

Is it related to your requirements?

@davidwhthomas
Copy link

davidwhthomas commented Nov 19, 2016

@nemenemsrouge yes!, that's the same request pattern in the Stripe date API.

They are using date[gte] and date[lte] similar to how we are using options[offset] and options[limit] etc..

Is there any example of how to define that style date API GET request via the Swagger / OpenAPI spec?

I had a google but it appears the Stripe API docs are generated via a custom in-house tool ( https://www.quora.com/What-software-powers-the-Stripe-API-documentation )

@jeremycohensolal
Copy link

@davidwhthomas I m sorry that I have no idea about how to do that...

Do you think using a "query" parameter and a type=object can do the job?

Maybe have to try...

@webron
Copy link
Member

webron commented Nov 21, 2016

Technically, you can describe that today by naming the parameter date[gte] and setting the type to string.

@DavidBiesack
Copy link

... but that does not scale to M fields by N operators. date[gte], date[gt], date[lte], date[lt], date[ne], then same for fields a, b, c. ... x, y, z, (We don't use notation such as this in our APis; I'm just noting that it is a stretch to enumerate all combinations.)

@webron
Copy link
Member

webron commented Nov 21, 2016

I didn't say it's a holistic solution, it can still be used to define explicit parameters if that's a requirement. I'm not familiar with Stripe's date API and it wasn't described as having varied inputs, only two. For two, it's definitely doable.

@jeremycohensolal
Copy link

Thanks a lot. I test that today !

@cdekok
Copy link

cdekok commented Jan 30, 2017

Is there any reason something like this won't work?
it works great when changing the parameter to body, it could just send the get param as

param1[0][name]=bla&param1[1][name]=foo

swagger: "2.0"
info:
  description: |
    This is a sample server Petstore server.
  version: "1.0.0"
  title: Swagger Petstore
  termsOfService: http://helloreverb.com/terms/
  contact:
    name: apiteam@swagger.io
  license:
    name: Apache 2.0
    url: http://www.apache.org/licenses/LICENSE-2.0.html
basePath: /v2
schemes:
  - http
paths:
  /test:
    get:
      summary: test
      description: test
      parameters:
        - name: param1
          in: query
          required: false
          description: test param1
          schema:
            type: array
            items:
              $ref: '#/definitions/bla'
      responses:
        200:
          description: OK
definitions:
  bla:
    type: object
    properties:
      name:
        type: string
        description: name of the object

@fehguy
Copy link
Contributor

fehguy commented Feb 1, 2017

See solution in #804

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests