How to serialize query object with custom delimeter - swagger

I have yaml file:
openapi: 3.0.1
info:
title: My API
version: v1
paths:
# /users;id=3;id=4?metadata=true
/users:
get:
parameters:
- in: query
name: offset
schema:
type: integer
description: The number of items to skip before starting to collect the result set
- in: query
name: limit
schema:
type: integer
description: The numbers of items to return
- in: query
name: origin
style: form
explode: false
schema:
type: object
properties:
city:
type: string
zip:
type: string
responses:
'200':
description: A list of users
When I click "execute" in https://editor.swagger.io, the generated Curl looks like this:
curl -X GET "https://editor.swagger.io/users?offset=2&limit=12&origin=city,atlanta,zip,303" -H "accept: */*"
However, I need it to be like this:
curl -X GET "https://editor.swagger.io/users?offset=2&limit=12&origin=city:atlanta|zip:303" -H "accept: */*"
Is it possible to do this? I could not find any info in documentation about setting custom delimeters.

Short answer: No.
Your specific use case isn't covered by serialize parameters and they follow the rfc6570 - it's a good idea to follow the standard if you want to design a well accepted web api.
You specified explode: false and style:form.
When you turn explode:true on you will get this instead:
city=atlanta&zip=303
When you specify style:deepObject you will get:
origin[city]=atlanta&origin[zip]=303
The spaceDelimited and pipeDelimited style won't work with objects.
Working without schema
You can of cause work without a schema and define your origin query parameter of type string.
The documentation should explain exactly what you expect and a little example will help people to use your API.
I won't use that pattern for an open API, but this can be a workaround for an internal API.

Related

swagger-ui docker image: Help understanding why query parameter using deepObject and explode does not result in the desired query

I'm trying to define OpenAPI for a query parameter that uses a simple type for a deepObject.
According to the OpenAPI spec, the following should work:
openapi: 3.0.3
info:
title: OpenAPI definition
version: 0.0.1
paths:
/example:
get:
parameters:
- name: foo
in: query
required: false
schema:
type: object
minProperties: 1
style: deepObject
explode: true
example: >
{
"bar": "baz"
}
responses:
"200":
description: OK
"400":
description: Bad request
"401":
description: Authorization info missing or invalid
"403":
description: Unauthorized
"404":
description: Not found
Should result in a query such as http://localhost:9080/example?foo[bar]=baz if you use the same input as the given example. However, what I'm getting is http://localhost:9080/example?bar=baz. I've searched around and quadruple checked my syntax to make sure I am doing what I think is being described around the web, but it still doesn't result in the output I think the OpenAPI spec is describing. I feel like I must be doing something wrong and am just not seeing it. Can anyone identify what I am doing wrong?
Note, I also posted this question to the discussion on the swagger-ui GitHub project.
Move style and explode outside the schema, to the parameter level:
parameters:
- name: foo
in: query
required: false
style: deepObject # <-------
explode: true # <-------
schema:
type: object
...

How to specify same path params at a single place for multiple endpoints in a swagger.yaml file [duplicate]

Let's say I've got a parameter like limit. This one gets used all over the place and it's a pain to have to change it everywhere if I need to update it:
parameters:
- name: limit
in: query
description: Limits the number of returned results
required: false
type: number
format: int32
Can I use $ref to define this elsewhere and make it reusable? I came across this ticket which suggests that someone wants to change or improve feature, but I can't tell if it already exists today or not?
This feature already exists in Swagger 2.0. The linked ticket talks about some specific mechanics of it which doesn't affect the functionality of this feature.
At the top level object (referred to as the Swagger Object), there's a parameters property where you can define reusable parameters. You can give the parameter any name, and refer to it from paths/specific operations. The top level parameters are just definitions and are not applied to all operations in the spec automatically.
You can find an example for it here - https://github.com/swagger-api/swagger-spec/blob/master/fixtures/v2.0/json/resources/reusableParameters.json - even with a limit parameter.
In your case, you'd want to do this:
# define a path with parameter reference
/path:
get:
parameters:
- $ref: "#/parameters/limitParam"
- $ref: "#/parameters/offsetParam"
# define reusable parameters:
parameters:
limitParam:
name: limit
in: query
description: Limits the number of returned results
required: false
type: integer
format: int32
offsetParam:
name: offset
in: query
description: Offset from which start returned results
required: false
type: integer
format: int32
For completeness, here's how it would look like in OpenAPI (a.k.a swagger v3):
openapi: "3.0.0"
servers:
- url: /v1
description: local server
paths:
/path:
get:
parameters:
- $ref: "#/components/parameters/limitParam"
components:
parameters:
limitParam:
name: limit
in: query
description: Limits the number of returned results
required: false
schema:
type: integer
minimum: 10
default: 10
multipleOf: 10 # matches 10, 20, ...
format: int32

How do I denote a list of a specific object as a return in a Swagger file?

I'm attempting to document a REST API using Swagger. Per REST API norms, I have endpoints for each Thing, and the GET protocols for each endpoint are bog standard normal: /thing/{id} returns a single Thing with the matching ID you give, and /thing/ returns a list of all valid Things.
The YAML for /thing/{id} is straightforward enough.
get:
operationId: GET_thing-id
tags:
- Thing
description: >-
Gets a specific Thing.
parameters:
- name: token
in: query
required: false
type: string
- name: Accept
in: header
required: false
type: string
responses:
'200':
description: ''
schema:
$ref: '#/definitions/Thing'
Where the $ref refers to the following, further down the YAML file:
definitions:
Thing:
title: Thing
type: object
properties:
id:
type: string
description: uuid.
But I find myself unsure how to handle the /thing/ endpoint, which is supposed to simply return a list of the models above. There seems to be no clear way to do this from perusing the Swagger spec, which I have done in depth at this point. Does anyone have guidance on how to handle this?
I figured it out. The problem was that there's slightly different things I need to define for an array and that was a real issue in tracking it down. The solution is:
definitions:
ThingArray:
title: ThingArray
type: array
items:
$ref: '#/definitions/Thing'
This can then be used in the /thing/ path and it looks perfectly reasonable.

How to define different query parameters for same path in OpenAPI (Swagger)?

I am starting a REST service, using Swagger Codegen. I need to have different responses for different parameters.
Example: <baseURL>/path can use ?filter1= or ?filter2=, and these parameters should produce different response messages.
I want my OpenAPI YAML file to document these two query params separately. Is this possible?
It is not supported in the 2.0 spec, and not in 3.0 either.
Here are the corresponding proposals in the OpenAPI Specification repository:
Accommodate legacy APIs by allowing query parameters in the path
Querystring in Path Specification
If you're still looking, I found out a way around this problem. It's a bit of a hack, but it works.
Basically, you can have two definitions to the same path by adding a slash (/) in the URL.
That way, you can set a response for <baseURL>/path with the ?filter1= parameter and set another response for <baseURL>//path with the ?filter2= parameter. It's also important that you give an unique operationId for each of the definitions.
paths:
/path/you/want:
get:
summary: Test
operationId: get1
parameters:
- name: filter1
type: string
in: path
required: true
responses:
200:
description: Successful response
schema:
$ref: '#/definitions/SomeResponse'
/path/you//want:
get:
summary: Another test
operationId: get2
parameters:
- name: filter2
type: string
in: path
required: true
responses:
200:
description: Successful response
schema:
$ref: '#/definitions/SomeOtherResponse'
I tried this with a path parameter and it worked just fine!
In swagger defining location,type explicitly is what defines these variables.
You have all the required fields to avoid collision of variables, for a json body you have to reference a declaration or use an example schema as shown below. For my case I have used a schema example rather than a declaration reference
/auth/account/password/reset/{userId}/{resetToken}:
post:
consumes:
- application/json
parameters:
- in: path
name: userId
type: string
required: true
- in: path
type: string
name: resetToken
required: true
- in: header
name: authorization
required: true
type: string
- in: body
name: body
required: true
schema:
type: object
example:
password: password
confirmPassword: password
responses:
"200":
description: OK
In Swagger you can add ? to make endpoints different.
i.e. /articles and /articles?:
When using ? in Swagger editor you will see error:
However on your final Swagger page there will be mark VALID
Additional information:
Remember about unique operationId for duplicated entries

swagger-ui adds api_token to query twice in CURL example

I am setting up our api documentation and i'm using swagger-spec and swagger ui.
I got everything working except that my CURL example adds our access_token twice
curl -X DELETE --header "Accept: application/json" "http://api host/api/user?filter%5Bid%5D%5BEQUAL%5D=1&access_token=Token_TOKANE&access_token=Token_TOKANE"
I renamed the api_key in swagger_ui index
var apiKeyAuth = new SwaggerClient.ApiKeyAuthorization("access_token", key, "query");
window.swaggerUi.api.clientAuthorizations.add("access_token", apiKeyAuth);
Screenshot
Swagger delete path
delete:
tags:
- User
summary: Delete user from you organization
operationId: deleteUser
description: Deletes a single by id. Gets id from filter param in query
parameters:
- name: filter[id][EQUAL]
in: query
type: integer
required: true
description: id to delete
responses:
200:
description: OK
schema:
$ref: '#/definitions/Message'
security:
- access_token: []
Security definition
securityDefinitions:
access_token:
type: string
in: query
name: access_token
The same issue can be seen in the swagger-ui live demo
If anyone knows of a fix or workaround i would appreciate it.
This has just been addressed in swagger-js. You can update your swagger-ui by building this locally and using npm link against the local build of swagger-ui. The release of swagger-ui with this fix is coming soon.

Resources