swagger example response not respecting nested allOf - swagger

When using the following swagger, the resulting endpoint has an example response that doesn't align with what I believe the swagger (and the models) dictate.
The swagger:
components:
examples: {}
headers: {}
parameters: {}
requestBodies: {}
responses: {}
schemas:
SubSubData:
type: object
properties:
subSubDataProp:
type: string
SubData:
allOf:
- $ref: '#/components/schemas/SubSubData'
- type: object
properties:
subDataProp:
type: string
Data:
allOf:
- $ref: '#/components/schemas/SubData'
- type: object
properties:
dataProp:
type: string
ExampleResponse:
type: object
properties:
data:
$ref: '#/components/schemas/Data'
info:
title: __PROJECT_NAME__
version: 1.0.0
description: |
Add your Swagger description here.
license:
name: ISC
contact:
name: Me
openapi: 3.0.0
paths:
/example:
get:
operationId: GetData
responses:
'200':
description: Ok
content:
application/json:
schema:
$ref: '#/components/schemas/ExampleResponse'
security: []
The expected response:
{
"data": {
"dataProp": "string",
"subDataProp": "string",
"subSubDataProp": "string"
}
}
Actual:
{
"data": {
"dataProp": "string"
}
}
Am I missing something? Or is this a bug in the swagger ui/openapi

It's a bug in Swagger UI:
https://github.com/swagger-api/swagger-ui/issues/5972
The workaround is to move paths before components.

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'

Invalid Swagger spec: swagger spec at "swagger.yml" is invalid against swagger specification 2.0

I am trying to use Swagger. Below is the swagger.yml file.
swagger: "2.0"
basePath: /myapp/api
info:
description: My description
title: My title
version: 0.1.0
produces:
- application/json
consumes:
- application/json
schemes:
- http
paths:
/contract:
get:
operationId: "Get contract"
description: Get information
parameters:
- in: path
name: contractId
description: ID
required: true
schema:
type: integer
responses:
200:
description: Information...
schema:
$ref: "#/definitions/contract"
404:
description: "Not found."
post:
operationId: "Create"
parameters:
- in: body
name: contractId
schema:
$ref: '#/definitions/requestBodies/contract'
responses:
200:
description: Success...
400:
description: Problem...
definitions:
contract:
title: Contract
type: object
properties:
name:
title: Name
type: string
services:
title: Services
type: array
items:
title: Service
$ref: '#/definitions/service'
xyz:
title: Xyz
$ref: '#/definitions/virtualMachine'
service:
title: Service
type: object
properties:
containerName:
title: ContainerName
type: string
...
contracts:
title: Contracts
type: array
items:
title: Contract
$ref: '#/definitions/contract'
xyz:
title: Xyz
type: object
properties:
serverId:
title: ServerID
type: string
contractId:
title: ContractID
type: uuid
...
requestBodies:
contract:
content:
application/json:
schema:
$ref: '#/definitions/contract'
When I try to generate the documentation, I get the following error:
swagger generate server -f swagger.yml
2020/10/26 15:43:31 validating spec /home/dalton/workspace/.../.../swagger.yml
The swagger spec at "/home/dalton/workspace/.../.../swagger.yml" is invalid against swagger specification 2.0. see errors :
- definitions.requestBodies.contract in body is a forbidden property
- "definitions.xyz.properties.contractId.type" must validate at least one schema (anyOf)
- definitions.xyz.properties.contractId.type in body must be of type array: "string"
What am I doing wrong?
To make this code pass in the Swagger validation, I had to:
Remove the schema in the contractId parameter (get method);
Remove the requestBodies definition and change the schema in the contract parameter (post method);
Change the type of the contractId in the Xyz definition (the uuid type is not supported by the version 2 of Swagger).
The fixed code is below:
swagger: "2.0"
basePath: /myapp/api
info:
description: My description
title: My title
version: 0.1.0
produces:
- application/json
consumes:
- application/json
schemes:
- http
paths:
/contract:
get:
operationId: "Get contract"
description: Get information
parameters:
- in: path
name: contractId
description: ID
required: true
type: integer
responses:
200:
description: Information...
schema:
$ref: "#/definitions/contract"
404:
description: "Not found."
post:
operationId: "Create"
parameters:
- in: body
name: contractId
schema:
$ref: '#/definitions/contract'
responses:
200:
description: Success...
400:
description: Problem...
definitions:
contract:
title: Contract
type: object
properties:
name:
title: Name
type: string
services:
title: Services
type: array
items:
title: Service
$ref: '#/definitions/service'
xyz:
title: Xyz
$ref: '#/definitions/virtualMachine'
service:
title: Service
type: object
properties:
containerName:
title: ContainerName
type: string
...
contracts:
title: Contracts
type: array
items:
title: Contract
$ref: '#/definitions/contract'
xyz:
title: Xyz
type: object
properties:
serverId:
title: ServerID
type: string
contractId:
title: ContractID
type: string
format: uuid
Maybe you can try to edit your swagger.yml in the online Swagger Editor.

Swagger send and receive array

openapi: "3.0.0"
info:
title: project
servers:
- url: http://example1.net/v3
- url: http://example/v3
paths:
/Pn/{PnId}/service1:
post:
summary: Pn data
description: |
can Pn the data
requestBody:
required: true
content:
application/json:
schema:
$ref: "#/components/schemas/dataInfo"
application/x-www-form-urlencoded:
schema:
$ref: "#/components/schemas/dataInfo"
parameters:
- name: PnId
in: path
description: PnId
required: true
schema:
$ref: "#/components/schemas/Pn"
responses:
'200':
description: status
content:
application/json:
schema:
$ref: "#/components/schemas/dataInfoStatus"
example: infoable
default:
description: error
content:
application/json:
schema:
$ref: "#/components/schemas/Error"
components:
schemas:
Error:
type: object
properties:
code:
type: integer
message:
type: string
required:
- message
Pn:
type: integer
format: int64
dataInfo:
type: string
dataInfoStatus:
type: string
enum: [infoable, non_infoable,ignorable]
I am sending a single dataInfo in request and getting single dataInfoStatus in response, but I will like to send and array of dataInfo and get an array of dataInfo status.
I tried following:
schema:
type:array
items:
$ref: "#/components/schemas/dataInfo"
but I get
Parser error bad indentation of a mapping entry
for items. I am following this.
How can I achieve sending dataInfo in request as an array of dataInfo and getting in response an array of dataInfoStatus?
You have to add one more space between type: and array, then the error message is gone:
schema:
type: array
items:
$ref: "#/components/schemas/dataInfo"
And you can add the info.version for the version of the openapi file.

Swagger examples for multilevel objects will not showup

I'm trying to show custom example just for 401 Response status code (overriding default example values) But the following code will not do this for some reason (default values stay in place) Status.Code and Status.Verbal will not set, also the "Agent" object will notgo into Content.
paths:
/api/Users/Login:
post:
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/LoginCredentials'
responses:
'200':
description: Login OK / Agent Object
content:
'*/*':
schema:
$ref: '#/components/schemas/RestResponse'
example:
Content:
schema:
$ref: '#/components/schemas/Agent'
'401':
description: Incorrect credentials
content:
'*/*':
schema:
$ref: '#/components/schemas/RestResponse'
example:
Status:
Verbal: Error
Code: 1074
Content: null
components:
schemas:
Agent:
type: object
RestResponse:
type: object
properties:
Status:
type: object
properties:
Verbal:
type: string
example: Success
Code:
type: string
format: int32
example: 104
Content:
type: object
Exception:
type: object
LoginCredentials:
type: object
required:
- UserName
- Password
properties:
UserName:
type: string
format: email
example: user#not.net
Password:
type: string
example: password
What I expect to see as response examples:
200:
{
"Status": {
"Verbal": "Success",
"Code": 104
},
"Content": "Agent{}"
}
401:
{
"Status": {
"Verbal": "Error",
"Code": 1074
},
"Content": null
}

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