Array of objects as an input parameter in swagger - 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

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 YAML Query (type object) Parameter Definition Error

I'm getting the following error:
Schema error at paths./cards/count.get.parameters[0] is not exactly
one from <#/definitions/parameter>,<#/definitions/jsonReference>
Here is my definition:
/cards/count:
get:
tags:
- "cards"
summary: "Number of Cards available"
description: "Excludes cards which the user has answered correctly in the past."
operationId: "countCards"
produces:
- "application/json"
parameters:
- name: "tagFilter"
in: "query"
description: "Input is optional - left blank will return all tags and a count"
type: "object"
properties:
tags_any:
type: "array"
items:
type: "integer"
format: "int64"
enum: [1,2,3]
tags_all:
type: "array"
items:
type: "integer"
format: "int64"
enum: [4,5,6]
tags_not:
type: "array"
items:
type: "integer"
format: "int64"
enum: [4,5,6]
I understand you can't use a schema definition as per this question: Swagger: Reusing an enum definition as query parameter
What do I need to modify to make the YAML compile without errors?
Objects in query parameters are not supported in OpenAPI/Swagger 2.0, but are supported in OpenAPI 3.0.
If you stick with OpenAPI 2.0, you'll need to split the object into separate parameters, like so:
parameters:
- in: query
name: tags_any
type: array
items:
type: integer
format: int64
enum: [1,2,3]
- in: query
name: tags_all
type: array
items:
type: integer
format: int64
enum: [4,5,6]
- in: query
name: tags_not
type: array
items:
type: integer
format: int64
enum: [4,5,6]
In OpenAPI 3.0, you can define the parameter as object and use the style and explode keywords to specify how this object should be serialized.
parameters:
- name: tagFilter
in: query
description: Input is optional - left blank will return all tags and a count
# Send the object as ?prop1=value1&prop2=value2
# This is the default serialization method for objects in query parameters
style: form
explode: true
schema:
type: object
properties:
tags_any:
type: array
items:
type: integer
format: int64
enum: [1,2,3]
tags_all:
type: array
items:
type: integer
format: int64
enum: [4,5,6]
tags_not:
type: array
items:
type: integer
format: int64
enum: [4,5,6]

Swagger POST body list

I've been searching fruitlessly on how to swagger spec a POST body with a list inside of it. How do I do it? Here's what I have:
/groups:
post:
summary: Creates a group
parameters:
- name: body
in: body
schema:
properties:
name:
type: string
description:
type: string
groupType:
type: string
enum: [ "open", "closed", "secret" ]
users:
type: string list # <--------- a list of strings
responses:
201:
description: Group created
default:
description: Group creation failed
For property being an array of string, please refer to https://github.com/swagger-api/swagger-codegen/blob/master/modules/swagger-codegen/src/test/resources/2_0/petstore.yaml#L660 as an example:
photoUrls:
type: array
items:
type: string

In Swagger, what is the responses looks like if I define the response object like this

I want this API to produce JSON in response HTTP body.
responses:
'200':
description: success
schema:
$ref: '#/definitions/Company'
'400':
description: client doesn't exist
definitions:
Company:
description: ''
type: object
properties:
id:
type: string
description: Empty when creating a record
name:
type: string
description: Not empty when creating record, or updating this field
email:
type: string
I think the response body would be:
{
"code": 200,
"company": {...company object...}
}
Is this correct? or
{
"200": {...company object...}
}
Here is the document that swagger tool generated:

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