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: [email protected]
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
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)
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.
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 : https://github.com/swagger-api/swagger-spec/issues/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).
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).
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.
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 [email protected] 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
https://github.com/swagger-api/swagger-spec/issues/380#issuecomment-140105023
.
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
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.
:+1:
+1
Link to parent #565
+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
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"
}
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
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?
@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 )
@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...
Technically, you can describe that today by naming the parameter date[gte] and setting the type to string.
... 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.)
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.
Thanks a lot. I test that today !
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¶m1[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: [email protected]
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
See solution in https://github.com/OAI/OpenAPI-Specification/pull/804
Most helpful comment
Technically, you can describe that today by naming the parameter
date[gte]and setting the type to string.