Swagger OAS3.0 Multiple responses in the same response code - swagger

I am using Swagger Hub to generate API and wanting to get multiple responses for the get request: https://virtserver.swaggerhub.com/factly/test/1.0.0/categories
Following is how I defined my API. When I execute the API I only get one category in response. How do I get all the three categories defined as a response? Any help is greatly appreciated.
openapi: 3.0.0
info:
description: This is the sample API for Core
version: "1.0.0"
title: Dega Core API
tags:
- name: Core
description: Operations related to Core
paths:
/categories:
get:
tags:
- Core
summary: gets all the categories
description: this is to get all the available categories
responses:
'200':
description: OK
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CategoryItem'
examples:
category1:
$ref: '#/components/examples/category1'
category2:
$ref: '#/components/examples/category2'
category3:
$ref: '#/components/examples/category3'
components:
schemas:
CategoryItem:
type: object
required:
- id
- name
- slug
- createdDate
properties:
id:
type: string
format: uuid
example: d290f1ee-6c54-4b01-90e6-d701748f0851
name:
type: string
example: Category 1
slug:
type: string
example: category-1
description:
type: string
example: This is a sample category
parent:
type: string
example: null
createdDate:
type: string
format: date-time
example: '2016-08-29T09:12:33.001Z'
examples:
category1:
value:
id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 1
slug: category-1
description: This is the sample description for Category 1
parent: null
createdDate: '2016-08-29T09:12:33.001Z'
category2:
value:
id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 2
slug: category-2
description: This is the sample description for Category 2
parent: null
createdDate: '2016-08-29T09:12:33.001Z'
category3:
value:
id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 3
slug: category-3
description: This is the sample description for Category 3
parent: d290f1ee-6c54-4b01-90e6-d701748f0851
createdDate: '2016-08-29T09:12:33.001Z'
servers:
- url: 'https://virtserver.swaggerhub.com/factly/test/1.0.0'
The response I am expecting is the following:
[{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"name": "Category 1",
"slug": "category-1",
"description": "This is the sample description for Category 1",
"createdDate": "2016-08-29T09:12:33.001Z"
},
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"name": "Category 2",
"slug": "category-2",
"description": "This is the sample description for Category 2",
"createdDate": "2016-08-29T09:12:33.001Z"
},
{
"id": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"name": "Category 3",
"slug": "category-3",
"description": "This is the sample description for Category 3",
"parent": "d290f1ee-6c54-4b01-90e6-d701748f0851",
"createdDate": "2016-08-29T09:12:33.001Z"
}]
Thanks,
Shashi

So your response is an array of objects, and you want to specify the response example containing an array with multiple items.
There are several ways to specify examples for array responses, but in any case the example must be a complete example, that is you cannot $ref'erence parts of an example (such as the values of individual array items). In other words, the example value cannot be built from partial $refs.
You can put the example inside your array schema, alongside type: array:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CategoryItem'
example:
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 1
slug: category-1
description: This is the sample description for Category 1
createdDate: '2016-08-29T09:12:33.001Z'
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 2
slug: category-2
description: This is the sample description for Category 2
createdDate: '2016-08-29T09:12:33.001Z'
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 3
slug: category-3
description: This is the sample description for Category 3
parent: d290f1ee-6c54-4b01-90e6-d701748f0851
createdDate: '2016-08-29T09:12:33.001Z'
Or add the example alongside the response schema:
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CategoryItem'
example:
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 1
slug: category-1
description: This is the sample description for Category 1
createdDate: '2016-08-29T09:12:33.001Z'
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
...
Or if you want to specify a description for the example, use the examples keyword (plural) as shown below. (But examples are currently not displayed in Swagger UI.)
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CategoryItem'
examples:
categoryWithThreeItems:
summary: Example of a category with three items
value:
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 1
slug: category-1
description: This is the sample description for Category 1
createdDate: '2016-08-29T09:12:33.001Z'
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
...
or put the whole example to the components/example section and $ref it. Note again, we can $ref whole examples only but not parts of an example.
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/CategoryItem'
examples:
categoryWithThreeItems:
$ref: '#/components/examples/categoryWithThreeItems'
components:
examples:
categoryWithThreeItems:
summary: Example of a category with three items
value:
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
name: Category 1
slug: category-1
description: This is the sample description for Category 1
createdDate: '2016-08-29T09:12:33.001Z'
- id: d290f1ee-6c54-4b01-90e6-d701748f0851
...

Related

How can I override example in openapi spec?

I've got the following spec:
---
openapi: 3.0.0
info:
title: Players API
version: 0.0.1-alpha1
paths:
/players/{id}:
get:
responses:
'200':
description: OK
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PlayerWrapper'
components:
schemas:
PlayerWrapper:
type: object
properties:
display_name:
type: string
example: 76ers
config:
description: |
The configuration of the player.
example: { spec: { team: 76ers, names: [ 1, 2 ] } }
allOf:
- $ref: '#/components/schemas/Player'
Player:
type: object
properties:
spec:
allOf:
- $ref: '#/components/schemas/BasicPlayer'
additionalProperties: false
BasicPlayer:
type: object
properties:
team:
type: string
names:
allOf:
- $ref: '#/components/schemas/Names'
additionalProperties: false
Names:
type: array
items:
type: string
example: [ Ben, Joel ]
I did verify on Swagger that it's indeed valid. The question is why I can see names: [ 1, 2 ] other than [ Ben, Joel ]. When I do remove that example thing (# example: { spec: { team: 76ers, names: [ 1, 2 ] } }), I can see Ben, Joel example:
Is there a way how I can force override / merge those example? As of now, I feel like my example gets overriden by either of those fields (i.e., either 76ers / [1, 2] or string / [Ben, Joel] but I'd like to get 76ers / [Ben, Joel] instead).
The structure in your schemas isn't quite right. The idea is to provide examples on the simple types (strings, int, etc) and the schema will structure it as required.
So dont put the example on config, put it on the nested simple types like this, ie BasicPlayer object should have the example on team as it's a string:
BasicPlayer:
type: object
properties:
team:
type: string
example: '76ers'
names:
allOf:
- $ref: '#/components/schemas/Names'
Similar with PlayerWrapper.config don't try and give a full object in the example, it gets composed by the member properties. So team gets an example, but Names example is composed from the child type.
PlayerWrapper:
type: object
properties:
display_name:
type: string
example: '76ers'
config:
description: |
The configuration of the player.
allOf:
- $ref: '#/components/schemas/Player'
Which should give you the expected example:
Here's the full swagger:
---
openapi: 3.0.0
info:
title: Players API
version: 0.0.1-alpha1
paths:
/players/{id}:
get:
parameters:
- $ref: '#/components/parameters/id'
responses:
'200':
description: OK
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PlayerWrapper'
components:
parameters:
id:
name: id
in: path
required: true
schema:
type: string
description: The id.
schemas:
PlayerWrapper:
type: object
properties:
display_name:
type: string
example: '76ers'
config:
description: |
The configuration of the player.
allOf:
- $ref: '#/components/schemas/Player'
Player:
type: object
properties:
spec:
allOf:
- $ref: '#/components/schemas/BasicPlayer'
additionalProperties: false
BasicPlayer:
type: object
properties:
team:
type: string
example: '76ers'
names:
allOf:
- $ref: '#/components/schemas/Names'
additionalProperties: false
Names:
type: array
items:
type: string
example:
- Ben
- Joel
Note it is possible to override schema examples with an example in the resource definition like this:
paths:
/players/{id}:
get:
parameters:
- $ref: '#/components/parameters/id'
responses:
'200':
description: OK
content:
application/json:
schema:
allOf:
- $ref: '#/components/schemas/PlayerWrapper'
example:
display_name: 76ers
config:
spec:
team: 76ers
names:
- 'Ben'
- 'Joel'

OpenAPI 3.0 - How to avoid adding "value" key when including examples by ref

With OpenAPI Is there a way to include examples by reference with the $ref: tag that doesn't not require adding the "value" key?
See examples I've added to the petstore.yaml:
openapi: "3.0.0"
info:
version: 1.0.0
title: Swagger Petstore
license:
name: MIT
servers:
- url: http://petstore.swagger.io/v1
paths:
/pets:
get:
summary: List all pets
operationId: listPets
tags:
- pets
parameters:
- name: limit
in: query
description: How many items to return at one time (max 100)
required: false
schema:
type: integer
format: int32
responses:
'200':
description: A paged array of pets
headers:
x-next:
description: A link to the next page of responses
schema:
type: string
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
example:
$ref: "#/components/examples/animals"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
post:
summary: Create a pet
operationId: createPets
tags:
- pets
responses:
'201':
description: Null response
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
/pets/{petId}:
get:
summary: Info for a specific pet
operationId: showPetById
tags:
- pets
parameters:
- name: petId
in: path
required: true
description: The id of the pet to retrieve
schema:
type: string
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
example:
$ref: "#/components/examples/garfield"
default:
description: unexpected error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Pet:
type: object
required:
- id
- name
properties:
id:
type: integer
format: int64
name:
type: string
tag:
type: string
Pets:
type: array
items:
$ref: "#/components/schemas/Pet"
Error:
type: object
required:
- code
- message
properties:
code:
type: integer
format: int32
message:
type: string
examples:
garfield:
id: 1
name: garfield
tag: cat
grumpycat:
id: 2
name: grumpycat
tag: cat
odie:
id: 3
name: odie
tag: dog
animals:
- $ref: "#/components/examples/garfield"
- $ref: "#/components/examples/grumpycat"
- $ref: "#/components/examples/odie"
openapi-generator-cli validate says it's invalid OpenAPI as does my OpenAPI plugin for VSCode. Error log output:
Validating spec (/local/petstore.yaml)
Errors:
-attribute components.examples.odie.name is unexpected
-attribute components.examples.garfield.id is unexpected
-attribute components.examples.grumpycat.name is unexpected
-attribute components.examples.animals is not of type `object`
-attribute components.examples.garfield.tag is unexpected
-attribute components.examples.garfield.name is unexpected
-attribute components.examples.odie.tag is unexpected
-attribute components.examples.grumpycat.id is unexpected
-attribute components.examples.grumpycat.tag is unexpected
-attribute components.examples.odie.id is unexpected
[error] Spec has 10 errors.
I can correct the errors by adding a value key like this:
examples:
garfield:
value:
id: 1
name: garfield
tag: cat
grumpycat:
value:
id: 2
name: grumpycat
tag: cat
odie:
value:
id: 3
name: odie
tag: dog
animals:
value:
- $ref: "#/components/examples/garfield"
- $ref: "#/components/examples/grumpycat"
- $ref: "#/components/examples/odie"
The problem with this is that, my examples now include the value property, which I don't want as it's not part of the schema:
{
"value": {
"id": 1,
"name": "garfield",
"tag": "cat"
}
}
Question: Is there a way for me to define the examples by $ref as I have done WITHOUT using introducing the "value" property?
The correct syntax is as follows:
components:
examples:
garfield:
value:
id: 1
name: garfield
tag: cat
grumpycat:
value:
id: 2
name: grumpycat
tag: cat
odie:
value:
id: 3
name: odie
tag: dog
animals:
summary: An array of two animals
value:
- id: 1
name: garfield
tag: cat
- id: 2
name: grumpycat
tag: cat
paths:
/pets:
get:
...
responses:
'200':
description: A paged array of pets
...
content:
application/json:
schema:
$ref: "#/components/schemas/Pets"
examples:
animals:
$ref: "#/components/examples/animals"
/pets/{petId}:
get:
...
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: "#/components/schemas/Pet"
examples:
garfield:
$ref: "#/components/examples/garfield"
grumpycat:
$ref: '#/components/examples/grumpycat'
odie:
$ref: '#/components/examples/odie'
Explanation:
Examples in the components/examples section must use the Example Object syntax. That is, the actual example value must be wrapped into the value key.
To reference examples from the components/examples section, you must use the examples keyword (plural; not singular example). examples is supported in parameters and in media types, but not in schemas.
Within the literal example value, $ref is not supported. That is, you cannot $ref a part of an example.

How to return an array of objects in SwaggerHub?

I am defining an API specification in SwaggerHub using OpenAPI 2.0. The /contacts request returns an array of contacts. The definition is below:
/contacts:
get:
tags:
- contacts
summary: Get all the contacts
description: This displays all the contacts present for the user.
operationId: getContact
produces:
- application/json
- application/xml
responses:
200:
description: successful operation
schema:
$ref: '#/definitions/AllContacts'
400:
description: Invalid id supplied
404:
description: Contact not found
500:
description: Server error
definitions:
AllContacts:
type: array
items:
- $ref: '#/definitions/ContactModel1'
- $ref: '#/definitions/ContactModel2'
ContactModel1:
type: object
properties:
id:
type: integer
example: 1
firstName:
type: string
example: 'someValue'
lastName:
type: string
example: 'someValue'
ContactModel2:
type: object
properties:
id:
type: integer
example: 2
firstName:
type: string
example: 'someValue1'
lastName:
type: string
example: 'someValue1'
For some reason, it only returns the second object not the whole array of objects.
I am using OpenAPI 2.0 and suspect that the arrays are not well supported in this version.
An array of objects is defined as follows. The value of items must be a single model that describes the array items.
definitions:
AllContacts:
type: array
items:
$ref: '#/definitions/ContactModel'
ContactModel:
type: object
properties:
id:
type: integer
example: 1
firstName:
type: string
example: Sherlock
lastName:
type: string
example: Holmes
By default, Swagger UI displays the array examples with just one item, like so:
[
{
"id": 1,
"firstName": "Sherlock",
"lastName": "Holmes"
}
]
If you want the array example to include multiple items, specify the multi-item example in the array model:
definitions:
AllContacts:
type: array
items:
$ref: '#/definitions/ContactModel1'
example:
- id: 1
firstName: Sherlock
lastName: Holmes
- id: 2
firstName: John
lastName: Watson
I realise this is a bit offtopic, but I landed here looking for an example for OpenApi 3.0. For others looking for the same thing, this is how to do it:
paths:
/product-category:
get:
summary: 'Returns all product categories'
operationId: readProductCategory
tags:
- productCategory
responses:
'200':
description: 'Details about all product categories'
content:
application/json:
schema:
type: array
items:
allOf:
- $ref: '#/components/schemas/Identifier'
- $ref: '#/components/schemas/ProductCategory'

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

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