swagger 3: schema for dictionary of dictionaries - swagger

I want to model a schema where response is dictionary of dictionaries:
{
'id1': {
'type': 'type1',
'active': true,
},
'id2': {
'type': 'type2',
'active': false,
},
...
...
}
I have defined:
components:
schemas:
accountData:
type: object
required:
- type
- active
properties:
type:
type: string
active:
type: boolean
accounts:
type: object
additionalProperties:
type: object
properties:
account-id:
type: object
$ref: '#/components/schemas/accountData'
Now I want to define '#/components/schemas/accounts' which is a repeating dictionary of '#/components/schemas/account'.
I am very new to OpenApi 3, I am unable to figure out how to do it.

You are almost there. The schema specified in additonalProperties corresponds to the value type in the <key, value> dictionary. In your example, the values are accountData objects, so you should use:
components:
schemas:
...
accounts:
type: object
additionalProperties:
$ref: '#/components/schemas/accountData'

Related

Object of object of array in Swagger

I have an input in the below format:
{"value" : {"codes": ["123","234"]} }
I have a swagger document as below but it does not yield the above result
/v1/search:
post:
summary: Get values
description: Get values
parameters:
- name: value
in: body
schema:
properties:
value:
type: array
items:
$ref: "#/definitions/Values"
definitions:
Values:
type: object
properties:
codes:
type: string
Any leads would be appreciated.
Try this. I used Value and Codes as schema names, but feel free to change them as you see fit.
- name: value
in: body
schema:
$ref: '#/definitions/Value'
definitions:
Value:
type: object
properties:
value:
$ref: '#/definitions/Codes'
Codes:
type: object
properties:
codes:
type: array
items:
type: string

Refer to self in OpenAPI 3.0

I have a data model definition in OpenAPI 3.0, using SwaggerHub to display the UI. I want one of the properties of a model to be related, which is an array of properties of the same model.
Foo:
properties:
title:
type: string
related:
type: array
items:
$ref: '#/components/schemas/Foo'
The parser doesn't seem to like this - the UI shows the related property as an empty array. Is this kind of self-reference possible in OpenAPI 3.0?
Your definition is correct, it's just Swagger UI currently does not render circular-referenced definitions properly. See issue #3325 for details.
What you can do is add a model example, and Swagger UI will display this example instead of trying to generate an example from the definition.
Foo:
type: object
properties:
title:
type: string
related:
type: array
items:
$ref: '#/components/schemas/Foo'
example: # <-------
title: foo
related:
- title: bar
- title: baz
related:
- title: qux
Alternatively, you can add an example just for the related array:
Foo:
type: object
properties:
title:
type: string
related:
type: array
items:
$ref: '#/components/schemas/Foo'
example: # <--- Make sure "example" is on the same level as "type: array"
- title: bar
- title: baz
related:
- title: qux
I got tired of this pesky situation, so I went with no example at all and chose to get rid of the items property, add a description element and use an empty array instead:
Foo:
type: object
properties:
title:
type: string
related:
type: array
description: Array of Foo elements
example: []
You can achieve that by a proxy model:
...
_MessageProxy:
description: Message
type: object
required:
- id
- user
- body
- publishedAt
properties:
id:
title: Message id
type: string
readOnly: true
example: '595f4acf828b0b766ad11290'
user:
$ref: '#/components/schemas/User'
Message:
allOf:
- $ref: '#/components/schemas/_MessageProxy'
- type: object
properties:
parent:
title: Parent
readOnly: true
allOf:
- $ref: '#/components/schemas/_MessageProxy'
...
Using a dummy model and cross reference:
Foo:
properties:
title:
type: string
related:
type: array
items:
$ref: '#/components/schemas/_Foo'
_Foo:
properties:
title:
type: string
related:
type: array
items:
$ref: '#/components/schemas/Foo'

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

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 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