Open API inherited example data - yaml

I'm using OpenAPI 3.0 to define an API for a service I am building. I'm running into an issue reusing schema components inside other components. For example, I have a Note object which contains a Profile object of the person who created the note. This works as expected by referencing the Profile object using the $ref keyword. The issue is when showing the example there isn't any data for the profile, and if I place the ref in the example like below it includes the actual OpenAPI block of Profile not just the example data for the Profile component.
I'm wondering if there is a way of reusing components in other components and also reusing the example set on those components?
Ex:
FullNote:
allOf:
- $ref: '#/components/schemas/BaseNote'
- type: object
title: A single note response
required:
- id
- dateCreated
- profile
properties:
id:
type: integer
format: int32
dateCreated:
type: integer
format: int64
profile:
type: object
$ref: '#/components/schemas/Profile'
example:
id: 123456789
dateCreated: 1509048083045
profile:
$ref: '#/components/schemas/Profile'

The example keyword (not to be confused with exampleS) does NOT support $ref. The whole example needs to be specified inline:
FullNote:
allOf:
- $ref: '#/components/schemas/BaseNote'
- type: object
...
example:
id: 123456789
dateCreated: 1509048083045
influencer:
prop1: value1 # <----
prop2: value2
Alternatively, you can use property-level examples - in this case tools like Swagger UI will build the schema example from property examples.
FullNote:
allOf:
- $ref: '#/components/schemas/BaseNote'
- type: object
...
properties:
id:
type: integer
format: int32
example: 123456789 # <----
dateCreated:
type: integer
format: int64
example: 1509048083045 # <----
profile:
# This property will use examples from the Profile schema
$ref: '#/components/schemas/Profile'
Profile:
type: object
properties:
prop1:
type: string
example: value1 # <----

Related

Spring boot code generated from swaggerhub is not able to throw 400 on additional properties

I've logged in to swaggerhub and generated a sample inventory API which is part of their template.
In codegen options selected spring as server. ticked on useBeanValidation checkbox. Generated the code, tested it. Validations are working properly as expected except only one thing. I don't want to allow any additional property on the POST payload.
NB: The openAPI specification doesn't have 'additionalProperties' flag specified. Which defaults it to 'false' in my understanding. I tried to explicitly specify the same too. but no luck. There is no exception thrown while I add an additionalProperty.
The OpenAPI specification
openapi: 3.0.0
servers:
# Added by API Auto Mocking Plugin
- description: SwaggerHub API Auto Mocking
url: https://virtserver.swaggerhub.com/xxxx/apionopenApi3/1.0.0
info:
description: This is a simple API
version: "1.0.0"
title: Simple Inventory API
contact:
email: you#your-company.com
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
tags:
- name: admins
description: Secured Admin-only calls
- name: developers
description: Operations available to regular developers
paths:
/inventory:
get:
tags:
- developers
summary: searches inventory
operationId: searchInventory
description: |
By passing in the appropriate options, you can search for
available inventory in the system
parameters:
- in: query
name: searchString
description: pass an optional search string for looking up inventory
required: false
schema:
type: string
- in: query
name: skip
description: number of records to skip for pagination
schema:
type: integer
format: int32
minimum: 0
- in: query
name: limit
description: maximum number of records to return
schema:
type: integer
format: int32
minimum: 0
maximum: 50
responses:
'200':
description: search results matching criteria
content:
application/json:
schema:
type: array
items:
$ref: '#/components/schemas/InventoryItem'
'400':
description: bad input parameter
post:
tags:
- admins
summary: adds an inventory item
operationId: addInventory
description: Adds an item to the system
responses:
'201':
description: item created
'400':
description: 'invalid input, object invalid'
'409':
description: an existing item already exists
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/InventoryItem'
description: Inventory item to add
components:
schemas:
InventoryItem:
type: object
additionalProperties: False
required:
- id
- name
- manufacturer
- releaseDate
properties:
id:
type: string
format: uuid
example: d290f1ee-6c54-4b01-90e6-d701748f0851
name:
type: string
example: Widget Adapter
releaseDate:
type: string
format: date-time
example: '2016-08-29T09:12:33.001Z'
manufacturer:
$ref: '#/components/schemas/Manufacturer'
Manufacturer:
required:
- name
properties:
name:
type: string
example: ACME Corporation
homePage:
type: string
format: url
example: 'https://www.acme-corp.com'
phone:
type: string
example: 408-867-5309
type: object
additionalProperties: False
Got 400 for this payload on post API.
{
"id": "7f125802-7840-4ff0-8ddb-7c78c0948987",
"name11111": "Widget Adapter",
"releaseDate": "2016-08-29T09:12:33.001Z",
"manufacturer": {
"name": "ACME Corporation",
"homePage": "",
"phone": "408-867-5309"
}
}
Expected 400 but didn't get on this payload on post
{
"id": "7f125802-7840-4ff0-8ddb-7c78c0948983",
"name": "Widget Adapter",
"releaseDate": "2016-08-29T09:12:33.001Z",
"manufacturer": {
"name": "ACME Corporation",
"homePage": "",
"phone": "408-867-5309"
},
"newkey" : "newValue"
}
Can anybody pls help on this.. I want to completely disallow additional properties and throw a 400 on those requests..
The default for additionalProperties is actually True, not False.
Adding false does not cause the swagger-codegen for Spring to actually disallow additional fields though, annoyingly enough. After a few hours of running in the wrong direction I found the solution:
In application.properties
spring.jackson.deserialization.FAIL_ON_UNKNOWN_PROPERTIES=true
I had been having the same trouble and have tried to leverage filters but have had problems tying the models that are used in the automatic deserialization of #RequestBody to the servlet request and keeping the behavior consistent across model changes. Coming to that conclusion required writing quite a bit of unnecessary boilerplate and wasting a lot of time.
I also tried to find a way to inject some behavior in the automatic use of the model or any model annotation that would change how the model automatically disregards additional fields without reporting the bad request. After exhausting the road of annotations I found the solution.

Reference multiple schema in a single schema

In swaggerhub I am trying to build a restful API. For which I have created n number of POJOs for request. I would like to represent them as references in other POJO example:
ClientInformation:
type: object
schema:
$ref: '#/definitions/EditClient'
$ref: '#/definitions/OtherDetails' #Duplicate mapping key error I see at this line
properties:
notes:
type: string
example: This is a test
description: A description
I tried , but didn't work. Kindly suggest.
If ClientInformation is a merger of the EditClient and OtherDetails schemas, you need allOf:
ClientInformation:
allOf:
- $ref: '#/definitions/EditClient'
- $ref: '#/definitions/OtherDetails'
- type: object
properties:
notes:
type: string
example: This is a test
description: A description
If ClientInformation has properties that are instances of other schemas, you can $ref the property schemas as follows:
ClientInformation:
type: object
properties:
notes:
type: string
example: This is a test
description: A description
foo:
$ref: '#/definitions/EditClient'
bar:
$ref: '#/definitions/OtherDetails'

how to pass multi value query params in swagger

I have following service in swagger.yml. The service is written so that page_id can be passed multiple times. e.g /pages?page_id[]=123&page_id[]=542
I checked this link https://swagger.io/specification/ but couldnt understand how could i update yml so i could pass id multiple times.
I see that i have to set collectionFormat but dont know how.
I tried updating it like below but no luck https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md.
it generates url like 'http://localhost:0000/pages?page_id=123%2C%20542`
'/pages':
get:
tags:
-
summary: get the list of pages
operationId: getPages
produces:
- application/json
parameters:
- name: page_id
in: query
description: some description
required: false
type: string
collectionFormat: multi
- name: page_detail
in: query
description: some description
required: false
type: string
responses:
'200':
description: OK
'401':
description: Authentication Failed
'404':
description: Not Found
'503':
description: Service Not Available
You are almost there. Name the parameter page_id[], make it type: array and use collectionFormat: multi:
parameters:
- name: page_id[]
in: query
description: some description
required: false
type: array
items:
type: string # or type: integer or whatever the type is
collectionFormat: multi
Note that the requests will be sent with the [ and ] characters percent-encoded as %5B and %5D, because they are reserved characters according to RFC 3986.
http://example.com/pages?page_id%5B%5D=123&page_id%5B%5D=456
From the docs:
parameters:
- name: id
in: path
description: ID of pet to use
required: true
schema:
type: array
style: simple
items:
type: string
You have to define the parameter as array.
How to add default values to the query parameter of type array:
parameters:
- name: 'liabilityType[]'
in: query
description: liabilityType filters the servicers list according to liability types.
required: false
schema:
type: array
items:
type: string
collectionFormat: multi
value:
- CAR
- HOUSE
I have attached a picture of how this code would look like in Swagger UI
[1]: https://i.stack.imgur.com/MSSaJ.png

Putting arrays inside of objects using Swagger 2.0 and YAML

I am currently learning how to document using Swagger because my company is evaluating using it as a standard way of documenting for upcoming projects.
I read online that using YAML is easier to read than using JSON, and since YAML is a subset of JSON I figured it would be alright.
I'm working on the response for the 200 code, I would like to represent something similar to the following structure:
responses:
200:
description: OK.
schema:
title: response
type: object
items:
properties:
title: user
type: array
items:
id:
type: string
name:
type: string
status:
type: integer
Basically I return an object called "response" that contains two variables: An array called "user" that contains several strings (I included just two for the sake of clarity) and another variable (outside of the "user" array) called "status" that contains an integer.
The above code doesn't work, and the editor notifies me that it isn't a "valid response definition".
I'm not sure how to tackle this. I'd appreciate some help on what I'm doing wrong.
Basically I return an object called "response" that contains two variables: An array called "user" that contains several strings (I included just two for the sake of clarity) and another variable (outside of the "user" array) called "status" that contains an integer.
Based on your description, the response is supposed to be as follows (assuming the response is JSON). Basically, you have an object with a nested object:
{
"user": {
"id": "12345",
"name": "Alice"
},
"status": 0
}
This response can be defined as follows:
responses:
200:
description: OK.
schema:
title: response
type: object
required: [user, status]
properties:
user:
type: object
required: [id, name]
properties:
id:
type: string
name:
type: string
status:
type: integer
For convenience, complex schemas with nested objects can be broken down into individual object schemas. Schemas can be written in the global definitions section and referenced from other places via $ref. This way, for example, you can reuse the same schema in multiple operations/responses.
responses:
200:
description: OK.
schema:
$ref: "#/definitions/ResponseModel"
definitions:
ResponseModel:
title: response
type: object
properties:
user:
$ref: "#/definitions/User"
status:
type: integer
required:
- user
- status
User:
type: object
properties:
id:
type: string
name:
type: string
required:
- id
- name

How to define array-of-objects as parameter?

I am quite new to Swagger, so this might be a basic question.
I am able to create .yml file for an API which takes an array of integers as parameter, as follows:
Add samples
---
tags:
- MY API
parameters:
- name: my_id
in: path
type: integer
required: true
description: Some des
- name: body
in: body
schema:
id: add_samples
required:
- sample_ids
properties:
sample_ids:
type: array
items:
type: integer
description: A list of sample ids to be added
responses:
'200':
description: Added samples.
'400':
description: Error adding samples.
This is what I send to the above API and everything works fine:
{"sample_ids": [475690,475689,475688]}
Now, instead of an array of integers, if I want to use some complex object as parameter, how to do it?
E.g. If this is what I want to send:
{"sample_ids": [{
"sample_id": "7",
"some_prop": "123"
},
{
"sample_id": "17",
"some_prop": "134"
}]}
How should the .yml file look? I have tried something like this and it doesn't seem to work:
Add sample
---
tags:
- Samples API
models:
Sample:
id: Sample
properties:
sample_id:
type: string
default: ""
description: The id for this sample
some_prop:
type: integer
description: Some prop this sample
parameters:
- name: body
in: body
schema:
id: add_sample
required:
- sample_ids
properties:
samples:
type: array
description: A list of samples to be added
items:
$ref: Sample
responses:
'201':
description: Created a new sample with the provided parameters
'400':
description: SOME ERROR CODE
This one seems to work, mostly:
Add sample
---
tags:
- Samples API
models:
Sample:
id: Sample
properties:
sample_id:
type: string
default: ""
description: The id for this sample
some_prop:
type: integer
description: Some prop this sample
parameters:
- name: body
in: body
schema:
id: add_sample
required:
- sample_ids
properties:
samples:
type: array
description: A list of samples to be added
items:
$ref: Sample
responses:
'201':
description: Created a new sample with the provided parameters
'400':
description: SOME ERROR CODE
Now only problem is, in the Swagger UI, it is not showing member variables and their default values. Rather is showing it as null:
{
"samples": [
null
]
}

Resources