How to define flat object structure in swagger body parameter - swagger

I'm using swagger 2.0 and need to define a post request to create an account object. The object data is passed in the body as a flat object structure:
Example body data:
{
first_name: "Sherlock",
last_name: "Holmes",
address: "Bakerstreet 221b",
# tax_id: not set, # optional
}
When I create the request doc in yaml:
definitions:
new_account:
properties:
first_name:
type: string
last_name:
type: string
address:
type: string
tax_id:
type: string
required:
- first_name
- last_name
- address
paths:
/accounts:
post:
summary: Create account
parameters:
- name: account
in: body
schema:
$ref: "#/definitions/new_account"
the documentation describes a body with exactly one element: account which itself contains some fields. However my structure is flat, no top node account.
If I leave out the name attribute, it's basically the same, only that the name column is empty in the resulting documentation and the whole structure is either required or not.
My current workaround is to list all parameters and set in: query but that's obviously wrong.
How to define this?

account is just the name of the body parameter. One usage is in the method signature in the API client generated by Swagger Codegen. In other words, account is not a top node (FYI, in Swagger spec 1.2, the body parameter must be named body)
Your definition above is correct for the example body data you provided.

Related

Can a swagger object passed as a parameter have default values in swagger-ui?

I define a path that takes MyObject as a parameter.
MyObject has properties for cats and dogs. These have default values.
In swagger-editor, the example doesn't show the default values, but try-it-out does create a MyObject with correct defaults.
In swagger-ui, I can see the defaults under Models, but not in the API. Is there a way to set these defaults ?
swagger: '2.0'
info:
title: pass object with default properties as a parameter
description: etc
version: "Draft 0.1.1"
host: example.com
basePath: /
produces:
- application/json
paths:
/myobject:
post:
summary: |
post an object.
parameters:
- name: myObject
in: body
required: true
schema:
type: array
items:
$ref: '#/definitions/MyObject'
responses:
200:
description: OK
definitions:
MyObject: # move to/models/model.yml
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
default: 9
dogs:
type: string
default: "fido"
Your usage of default is wrong. You probably want example instead.
default is only used with optional fields and is handled on the server side. That is, if the client does not supply a value in the payload, the server will use the default value.
Consider this User model:
definitions:
User:
type: object
required:
- username
properties:
username:
type: string
role:
type: string
enum:
- user
- poweruser
- admin
default: user
The role property is optional and defaults to user. So, if the client sends the payload without role:
{
"username": "bob"
}
the server will assume role=user.
In your case, it looks like you want to provide example values for the fields. This is what the example keyword is for:
definitions:
MyObject:
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
example: 9 # <---
dogs:
type: string
example: fido # <---
It seems like there are 2 kinds of defaults:
server-side: variable is not required and server will assume a value for it if it is not given definition from OpenApi v3.0 spec
client side: variable is required and must be only one value (for example headers)
For a client-side default, we can define it by setting required=True and enum to the only allowed value. See this example below:
swagger: "2.0"
info:
title: "some api"
description: "a description"
version: "1.0.0"
host: "example.com"
basePath: "/api"
schemes:
- "http"
paths:
/myobject:
post:
summary: |
post an object.
parameters:
- name: myObject
in: body
required: true
schema:
type: array
items:
$ref: '#/definitions/MyObject'
responses:
200:
description: OK
definitions:
MyObject:
type: object
description: Contains default properties
required:
- cats
- dogs
properties:
cats:
type: number
enum:
- 9
dogs:
type: string
enum:
- fido
And you can see it work in the swagger-editor here: https://editor.swagger.io/
The default parameter is a bit confusing because swagger 2.0 initially described the default parameter without specifying a server or client reference frame.
Swagger 2.0 spec
Defines schema default as
default (Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object)
OpenAPI v3.0 spec
default - The default value represents what would be assumed by the consumer of the input as the value of the schema if one is not provided. Unlike JSON Schema, the value MUST conform to the defined type for the Schema Object defined at the same level. For example, if type is string, then default can be "foo" but cannot be 1.

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

Microsoft Flow states that "This operation has no inputs." for an operation in my Custom API

I've created a swagger file that attempts to define the operations that I need from the Microsoft Graph API.
This API requires a couple of slightly complex data types to do things like creating users do I've therefore built these object and properties as a schema that provides a parameter 'parameters' in: body. See the snippets below.
I can register this Custom API in Flow but when I attempt to use an operation that has an in body parameter the action in Flow states that "This operation has no inputs."
/users:
post:
tags:
- User
summary: Create User
operationId: UserCreate
description: >-
Use this API to create a new User. The request body contains the user to
create. At a minimum, you must specify the required properties for the
user. You can optionally specify any other writable properties.
parameters:
- name: parameters
in: body
required: true
schema:
$ref: '#/definitions/UserCreateParameters'
description: Parameters to create a user.
responses:
'201':
description: >-
Created. Indicates success. The new user is returned in the response
body.
schema:
$ref: '#/definitions/User'
default:
description: Error response
schema:
$ref: '#/definitions/GraphError'
Definitions
PasswordProfile:
properties:
password:
type: string
description: Password
forceChangePasswordNextLogin:
type: boolean
description: Force change password on next login
required:
- password
description: Contains the password profile associated with a user.
UserCreateParameters:
properties:
accountEnabled:
type: boolean
description: Enable the account. If it is enabled then true else false.
displayName:
type: string
description: User display name
passwordProfile:
$ref: '#/definitions/PasswordProfile'
userPrincipalName:
type: string
description: >-
The user principal name (someuser#contoso.com). It must contain one of
the verified domains for the tenant.
mailNickname:
type: string
description: The mail alias for the user
immutableId:
type: string
description: >-
Needs to be specified if you are using a federated domain for the
user's userPrincipalName (UPN) property while creating a new user
account. It is used to associate an on-premises Active Directory user
account to their Azure AD user object.
required:
- accountEnabled
- displayName
- passwordProfile
- userPrincipalName
- mailNickname
description: Request parameters for create a new work or school account user
I've discovered that the definitions, even thought they are valid Swagger and are validated by Flow, needs to have a type of 'object'.
As such, UserCreateParameters should be followed but type: object. E.g.
UserCreateParameters:
type: object
properties:
I've now included this at the start of every definition and all the fields are appearing as expected.

Not a valid parameter definition for Swagger query?

# GET verb version of the "GetClientsForGadget" method from the original ASMX Service
/clients/ProspectClient/roleandcstbased/{OrgNmFilter}/{SortNm}?{UserName}:
get:
tags:
- Client
summary: Merging of GetClientsforGadget and GetClientsForUser
operationId: ClientsForGadgetGET
parameters:
- name: OrgNmFilter
in: path
description: Organization Name Filter
required: true
type: string
- name: SortNm
in: path
description: Sort Field
required: true
type: string
- name: UserName
in: query
description: User's Identity
required: false
type: string
responses:
200:
description: Output results for GetClientsForGadget endpoint
schema:
$ref: '#/definitions/ClientOutput'
Swagger is giving me not a valid parameter definition for this query parameter. If I remove all references to Username in the path and parameter definition, no issues.
According to the Swagger Specification, I believe I'm using query parameters right, but somehow it's not.
Realized the issue was in path. The path does not need to include the query parameter.
/clients/ProspectClient/roleandcstbased/{OrgNmFilter}/{SortNm}?{UserName}:
/clients/ProspectClient/roleandcstbased/{OrgNmFilter}/{SortNm}:
It only needs the query to be defined in parameters. Otherwise bugs the whole thing out.

Use object type query param in swagger documentation

I have a GET route where I would like to encode an object parameter in the url as a query string.
When writing the swagger documentation I basically get errors that disallow me to use schema/object types in a query type parameter:
paths:
/mypath/:
get:
parameters
- in: path
name: someParam
description: some param that works
required: true
type: string
format: timeuuid #good param, works well
- $ref: "#/parameters/mySortingParam" #this yields an error
parameters:
mySortingParam
name: paging
in: query
description: Holds various paging attributes
required: false
schema:
type: object
properties:
pageSize:
type: number
cursor:
type: object
properties:
after:
type: string
format: string
The request query param having an object value would be encoded in an actual request.
Even though swagger shows an error at the top of the screen the object is rendered correctly in the swagger UI editor, however with that error floating on top of the documentation.
I don't think you can use "object" as query parameter in Swagger spec as query parameter only supports primitive type (https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#data-types)
This is now possible with OpenAPI 3.0.
parameters:
- in: query
name: values
schema:
type: object
properties:
genre_id:
type: integer
author_id:
type: integer
title:
type: string
example:
{
"genre_id": 1,
"author_id": 1
}
style: form
explode: true
Here you can use style and explode keywords to specify how parameters should be serialised.
style defines how multiple values are delimited. Possible styles depend on the parameter location – path, query, header or cookie.
explode (true/false) specifies whether arrays and objects should
generate separate parameters for each array item or object property.
For the above example the url will be:
https://ebookstore.build/v1/users/books/search?genre_id=1&author_id=1
For more information on describing parameters with OpenAPI v3 and parameter serialisation, please refer here.
This is possible, just not with OpenAPI 2.0. OpenAPI 3.0 describes how this is possible here:
https://swagger.io/docs/specification/describing-parameters/
parameters:
- in: query
name: filter
# Wrap 'schema' into 'content.<media-type>'
content:
application/json: # <---- media type indicates how to serialize / deserialize the parameter content
schema:
type: object
properties:
type:
type: string
color:
type: string
In the meantime you could just have the query parameter as a plain old string type and then perform the serialization manually, then set the query parameter as required. This is what I'm doing until Swagger UI fully supports OpenAPI 3.0.

Resources