Different requestBody Correct Method in Swagger OpenApi3 - swagger

I have a form data like this:
{
"form_id": 55426,
"submission_id": 28,
"status": 1,
"user_id": "74285"
}
but sometimes status and user_id will not be passed and it will be like
and user and type_id will be there
{
"form_id": 55426,
"submission_id": 28",
"user": true,
"type_id" : 1
}
. So what is the correct method to define requestBody?
Is it correct to define like this,
requestBody:
description: Check integration status.
content:
application/json:
schema:
type: object
properties:
form_id:
type: integer
example: 236089
submission_id:
type: integer
example: 1
status:
type: integer
example: 236089
user_id:
type: integer
example: 1
user:
type: integer
example: 1
type_id
type: integer
example: 1
and in the tryout option, I should pass only relevant properties only? Or is there any option to describe differently multiple requestBody?

Related

swagger 3/OAS 3 submit file data along with regular data mutlipart request

I have the following swagger code addCustomer for sending a request that includes an image along with other json data. When I run code from swagger hub; it just sends json. Am I defining this right? Shouldn't it send multipart request?
post:
tags:
- customers
summary: Add a new customer to the store
description: ''
operationId: addCustomer
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/NewCustomerWithImageUrl'
application/xml:
schema:
$ref: '#/components/schemas/NewCustomerWithImageUrl'
multipart/form-data:
schema:
$ref: '#/components/schemas/NewCustomerWithImage'
description: Customer object that needs to be added to the store
required: true
NewCustomerWithImage:
type: object
allOf:
- $ref: '#/components/schemas/NewCustomer'
properties:
Image:
type: string
format: binary
Person:
type: object
required:
- first_name
properties:
first_name:
type: string
example: John
last_name:
type: string
example: Doe
email:
type: string
example: john#example.com
phone_number:
type: string
example: 555-555-5555
address_1:
type: string
example: 123 Nowhere Street
address_2:
type: string
example: Apartment 123
city:
type: string
example: Rochester
state:
type: string
example: New York
zip:
type: string
example: '14445'
country:
type: string
example: United States
comments:
type: string
example: A great customer
custom_fields:
type: object
minProperties: 0
maxProperties: 10
additionalProperties:
type: string
example:
secondary phone number: '555-555-5555'
NewCustomer:
type: object
allOf:
- $ref: '#/components/schemas/Person'
properties:
company_name:
type: string
example: PHP Point Of Sale
tier_id:
type: integer
format: uuid
example: 0
account_number:
type: string
example: '3333'
taxable:
type: boolean
example: false
tax_certificate:
type: string
example: '1234'
override_default_tax:
type: boolean
example: false
tax_class_id:
type: integer
format: uuid
example: 0
balance:
type: number
format: float
example: 22.99
credit_limit:
example: null
points:
type: integer
format: int32
example: 333
disable_loyalty:
type: boolean
example: true
amount_to_spend_for_next_point:
type: number
format: float
readOnly: true
example: 10.00
remaining_sales_before_discount:
type: integer
format: int32
readOnly: true
example: 0
xml:
name: Customer
Json sent:
{"first_name":"John","last_name":"Doe","email":"john#example.com","phone_number":"555-555-5555","address_1":"123 Nowhere Street","address_2":"Apartment 123","city":"Rochester","state":"New York","zip":"14445","country":"United States","comments":"A great customer","custom_fields":{"secondary phone number":"555-555-5555"},"company_name":"PHP Point Of Sale","tier_id":0,"account_number":"3333","taxable":false,"tax_certificate":"1234","override_default_tax":false,"tax_class_id":0,"balance":22.99,"credit_limit":null,"points":333,"disable_loyalty":true,"Image":"string"}
Swagger Hub File:
https://app.swaggerhub.com/apis/PHP-Point-Of-Sale/PHP-Point-Of-Sale/1.0#/customers/addCustomer
1) Swagger UI (which SwaggerHub uses) does not yet support form data and file upload for OpenAPI 3.0 definitions. Follow this issue for status updates: https://github.com/swagger-api/swagger-ui/issues/3641 UPD: Swagger UI now supports file uploads for OAS3.
2) If "request that includes an image along with other JSON data" means a multipart request like this –
POST /foo HTTP/1.1
Content-Type: multipart/form-data; boundary=ABCDEF123
--ABCDEF123
Content-Disposition: form-data; name="Customer"
Content-Type: application/json
{
"foo": "bar"
}
--ABCDEF123
Content-Disposition: form-data; name="Image"; filename="image1.png"
Content-Type: application/octet-steam
{…image content…}
--ABCDEF123--
then the request body definition should look like this:
requestBody:
content:
...
multipart/form-data:
schema:
type: object
properties:
Customer: # <--- name of the part in a multipart request
$ref: '#/components/schemas/NewCustomer'
Image: # <--- name of the part in a multipart request
type: string
format: binary
required:
- Customer
- Image
More information:
How to describe a multipart response using OpenAPI (Swagger)? here on SO
Special Considerations for multipart Content in the OpenAPI 3.0 Specification
Multipart Requests on swagger.io
File upload is supported in Open API v 3.0.3
Here's what my swagger.json looks like:
"/media/upload": {
"post": {
"tags": ["Media"],
"name": "Upload Media",
"description": "Uploads a Media file to the server.",
"requestBody": {
"required": true,
"content": {
"multipart/form-data": {
"schema": {
"type": "object",
"properties": {
"media": {
"type": "string",
"format": "base64"
}
}
}
}
}
}
}
}
Here's how it show up in swagger:

Swagger UI: Multiple anonymous objects in array

I am writing Swagger documentation for an API, and one endpoint returns many nested objects and parameters.
There is one returned array, however, which does not return regular parameters. Instead, it returns two anonymous objects that hold the parameters.
"balanceDisplaySettings": [
{
"type": "Balance",
"label": "Current",
"visible": true,
"primary": false
},
{
"type": "AvailableBalance",
"label": "Available",
"visible": true,
"primary": true
}
]
YAML
swagger: '2.0'
schemes:
- https
consumes:
- application/json
produces:
- application/json
paths:
"/Path/":
responses:
'200':
description: OK
schema:
type: object
properties:
balanceDisplaySettings:
type: array
items:
type: object
properties:
type:
type: "Balance"
description: description
label:
type: "Available"
description: description
visible:
type: boolean
description: description
primary:
type: boolean
description: description
type: object
properties:
type:
type: "AvailableBalance"
description: description
label:
type: "Available"
description: description
visible:
type: boolean
description: description
primary:
type: boolean
description: description
Looking at swagger's documentation for Describing Request Body, there is seemingly no way to handle objects without a name.
How do I (Using YAML) document this type of response body in Swagger-UI?
An array of objects is defined like this:
type: array
items:
type: object
properties:
prop1:
type: string
prop2:
type: integer
# etc.
In your example, the response contains an object with the property balanceDisplaySettings, and this property contains an array of objects. This can defined as follows:
paths:
/Path:
get:
responses:
200:
description: OK
schema:
type: object
properties:
balanceDisplaySettings:
type: array
items:
type: object
properties:
type:
type: string
label:
type: string
visible:
type: boolean
primary:
type: boolean
Note that the schema defines the response structure, meaning you don't need to specify the actual values ("Balance", "AvailableBalance", etc.) anywhere. However, if you want to display the example from your post (array with 2 objects) as an example in Swagger UI, you can add it like this:
balanceDisplaySettings:
type: array
items:
type: object
properties:
type:
type: string
label:
type: string
visible:
type: boolean
primary:
type: boolean
example: # <-- example of array of 2 objects
- type: Balance
label: Current
visible: true
primary: false
- type: AvailableBalance
label: Available
visible: true
primary: true
Finally, you may want to split the inline nested schema to make the spec more modular.
paths:
/Path:
get:
responses:
200:
description: OK
schema:
$ref: '#/definitions/MyResponseObject'
# |
definitions: # |
# TODO: better name # |
MyResponseObject: # <--------------+
type: object
properties:
balanceDisplaySettings:
type: array
items:
$ref: '#/definitions/BalanceDisplaySetting'
example: # |
- type: Balance # |
label: Current # |
visible: true # |
primary: false # |
- type: AvailableBalance # |
label: Available # |
visible: true # |
primary: true # |
# |
BalanceDisplaySetting: # <--------+
type: object
properties:
type:
type: string
example: Balance
label:
type: string
example: Current
visible:
type: boolean
boolean:
type: boolean
Another solution is the oneOF parameter.
With it you can use multiple anonymous objects as you want.
Just create some definitions and call them inside items:
"type": "array",
"items": {
"oneOf": [
{ "$ref": "#/components/schemas/Schema1" },
{ "$ref": "#/components/schemas/Schema2" }
]
}
You can read more about here:
https://community.smartbear.com/t5/Swagger-Open-Source-Tools/Can-You-Define-a-Response-Consisting-of-an-Array-With-Two/td-p/186919
Hope it helps

Define array of multiple models in Swagger 2.0

This is my first foray into Swagger so please be gentle.
I have the following definitions:
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
$ref: '#/definitions/Indicator'
Indicator:
type: object
properties:
type:
type: string
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
BBANDS:
properties:
type:
type: string
default: BBANDS
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
nbdevup:
type: integer
format: int32
default: 2
nbdevdn:
type: integer
format: int32
default: 2
matype:
type: integer
format: int32
default: 0
DEMA:
properties:
type:
type: string
default: DEMA
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
So Payload has a property called indicator which is an array of Indicators. The BBANDS and DEMA are models which are of type Indicator (which I know doesn't translate to Swagger). What I'd like to do is define an array of the actual models with their defaults, in this case BBANDS and DEMA. Something like this:
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
- '#/definitions/BBANDS'
- '#/definitions/DEMA'
or
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
- $ref '#/definitions/BBANDS'
- $ref '#/definitions/DEMA'
Neither of which work of course. The reason is while the Indicator model describes an indicator correctly, different indicators can have a different parameter set.
Is there a way to essentially define a list of several models or perhaps map the BBANDS and DEMA models into Indicator?
Edit: Result of using #Helen's first suggestion in the Swagger Editor
Swagger/OpenAPI 2.0 does not support multiple types for items, but there are a couple of ways to describe what you need.
Option 1 - Model Inheritance
As long as you have one field that is common between the models and can be used to distinguish between them, you can use model inheritance:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaDiscriminator
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#composition-and-inheritance-polymorphism
In your example, this property is type (type="BBANDS" or type="DEMA"). So you can:
Inherit the BBANDS and DEMA models from Indicator by using allOf.
Add discriminator: type to Indicator to indicate that the type property will be used to distinguish between the sub-models.
Define Payload as an array of Indicator. This way it can actually be an array of BBANDS or an array of DEMA.
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
$ref: '#/definitions/Indicator'
Indicator:
type: object
properties:
type:
type: string
# Limit the possible values if needed
#enum:
# - BBANDS
# - DEMA
computeOn:
type: array
items:
type: string
default:
- close
# The "type" property will be used to distinguish between the sub-models.
# The value of the "type" property MUST be the schema name, that is, "BBANDS" or "DEMA".
# (Or in other words, the sub-model schema names must match possible values of "type".)
discriminator: type
required:
- type
BBANDS:
allOf:
- $ref: '#/definitions/Indicator'
- type: object
properties:
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
nbdevup:
type: integer
format: int32
default: 2
nbdevdn:
type: integer
format: int32
default: 2
matype:
type: integer
format: int32
default: 0
DEMA:
allOf:
- $ref: '#/definitions/Indicator'
- type: object
properties:
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
Option 2 - Single Model
If all parameters are integer, you can have a single model Indicator with parameters defined as a hashmap. But in this case you lose the ability to define the exact parameters for specific indicator types.
definitions:
Indicator:
type: object
properties:
type:
type: string
enum:
- BBANDS
- DEMA
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
# This is a common parameter in both BBANDS and DEMA
timeperiod:
type: integer
format: int32
default: 5
# This will match additional parameters "nbdevup", "nbdevdn", "matype" in BBANDS
additionalProperties:
type: integer
AFAIK in array type can holds one type, if you want to have multiple types under an array, then need to define another super type and wrap the subtypes in it ( May be using object type ) like bellow. This restriction is because swagger-2.0 doesn't support all the features of json-schema.org, oneOf, anyOf, allOf etc are some of it.
But you can make use the third party extension option available with swagger-2.0. Where you can name a Key with x-, so that means you can include these oneOf like x-oneOf and when parsing the schema you do that using json-schema parser along with swagger schema parser.
One such example is given bellow,
Json-schema
{
"id": "http://some.site.somewhere/entry-schema#",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "schema for an fstab entry",
"type": "object",
"required": [
"storage"
],
"properties": {
"storage": {
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/diskDevice"
}
]
},
"deviceList": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/Device"
}
}
},
"definitions": {
"diskDevice": {
"type": "object",
"properties": {
"label": {
"type": "string"
}
},
"required": [
"label"
]
},
"blockDevice": {
"type": "object",
"properties": {
"blockId": {
"type": "number"
}
},
"required": [
"blockId"
]
},
"CharDevice": {
"type": "object",
"properties": {
"charDeviceName": {
"type": "string"
}
},
"required": [
"charDeviceName"
]
},
"Device": {
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/diskDevice"
},
{
"$ref": "#/definitions/blockDevice"
},
{
"$ref": "#/definitions/CharDevice"
}
]
}
}
}
Data or Payload
{
"storage": {"label": "adsf"},
"deviceList": [{"label": "asdf"}, {"blockId": 23}, {"charDeviceName": "asdf"}]
}
Use this site for play around with your sample data - http://www.jsonschemavalidator.net/
Note the deviceList property and how it got constructed. Hope this helps you.

Array of objects as an input parameter in swagger

I'm trying to describe the following post parameter in swagger:
{
"sources": [
{
"id": 101,
"parentId": 201
},{
"id": 102,
"parentId": 201
},{
"id": 102,
"parentId": 202
}
],
"destinationId": 301,
"param1": "value 1",
"param2": "value 2",
}
The issue is that the sources is an array of objects, that swagger does not seem to support. Here is what I tried:
paths:
/bulk-action:
post:
parameters:
- name: sources
in: formData
type: array
enum:
$ref: '#/definitions/BulkSource'
- name: destinationId
in: formData
type: integer
- name: param1
in: formData
type: string
- name: param2
in: formData
type: string
definitions:
BulkSource:
type: object
properties:
id:
type: integer
parentId:
type: integer
Any idea on how to work around this limitation?
If I understand correctly, your request body to post is a json object instead of form. In such case, your swagger document need to be modified as follows:
When request body is json, a parameter with in: body is used instead of multiple parameters of in: formData.
If in is body, a schema object is required.
Defined the json properties under schema. If the property type is array, items object is required.
Following is an example:
paths:
/bulk-action:
post:
consumes:
- application/json
parameters:
- name: body
in: body
schema:
properties:
sources:
type: array
items:
$ref: '#/definitions/BulkSource'
destinationdId:
type: integer
responses:
200:
description: OK
definitions:
BulkSource:
type: object
properties:
id:
type: integer
parentId:
type: integer

Swagger composition / inheritance

I'm trying to document a REST API using Swagger. A simplified JSON response from our API looks like:
{
"data": {
"type": "person"
"id": "1"
"attributes": {
"name": "Joe"
"age": 32
...
}
"links": {
...
}
}
}
or
{
"data": {
"type": "job"
"id": "22"
"attributes": {
"name": "Manager"
"location": "Somewhere"
...
}
"links": {
...
}
}
}
Their Swagger definitions for a successful GET might look like:
'200':
description: OK.
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
type:
type: string
attributes:
$ref: '#/definitions/person'
or
'200':
description: OK.
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
type:
type: string
attributes:
$ref: '#/definitions/job'
There's potentially a lot of repetition like this in our Swagger file. Is it possible to define these responses to share the common parts? i.e. I don't want to type out or copy/paste this part tens of times:
'200':
description: OK.
schema:
type: object
properties:
data:
type: object
properties:
id:
type: string
type:
type: string
I couldn't see how this would work using the discriminator field, or using $ref.
You can use allOf to do composition (in conjunction with discriminator you can do inheritance but it's not really functionnal)
allOf is used with an array of schema or reference, it will create a new definition containing all properties of all definitions in the array.
Given that you want some of your definitions to share id and type properties, it is done this way:
swagger: '2.0'
info:
version: 1.0.0
title: API
paths: {}
definitions:
SharedDefinition:
properties:
id:
type: string
type:
type: string
Person:
allOf:
- $ref: '#/definitions/SharedDefinition'
- properties:
firstname:
type: string
lastname:
type: string
JobSubDefinition:
properties:
name:
type: string
Job:
allOf:
- $ref: '#/definitions/SharedDefinition'
- $ref: '#/definitions/JobSubDefinition'
In this example:
Person = SharedDefinition + inline definition
Job = SharedDefinition + JobSubDefinition
More about this in
Writing OpenAPI (Swagger) Specification Tutorial – Part 4 – Advanced Data Modeling (disclosure: I wrote this tutorial)
OpenAPI Specification#models-with-composition

Resources