Unable to add ArrayList in swagger [duplicate] - swagger-ui

This question already has answers here:
How to add multiple example values for an array in OpenAPI/Swagger?
(3 answers)
Closed 1 year ago.
I want my OpenAPI spec to display the list of both the objects like below but I'm unable to do so.
[
{
"studentID": 1,
"studentName": "Ram"
},
{
"studentID": 2,
"studentName": "Shyam"
}
]
Swagger Spec in editor.swagger.io:

example keyword should be at the same level of items:
200:
description: success response
content:
application/json:
schema:
type: array
items:
properties:
studentID:
type: integer
studentName:
type: string
example:
- { "studentID": 1, "studentName": "Ram" }
- { "studentID": 2, "studentName": "Shyam" }

Related

Is parent definition in API request body required if it's partial sub child properties are marked required?

Suppose I have the following OpenAPI definition (ignore the indentation or missing attributes):
FooData:
type: object
additionalProperties: false
description: Holds the foo data Information.
required:
- id
- contact
properties:
id:
description: Identifier
type: string
maxLength: 255
minLength: 1
pattern: ^[a-zA-Z0-9\-]{1,255}$
identity:
description: Holds customer identity info.
$ref: '#/MyIdentity' ....
MyIdentity:
type: object
additionalProperties: false
description: Holds the customer identity information.
required:
- userId
properties:
userId:
type: integer
format: int64
minimum: 0
maximum: 9223372036854775807
description: Unique Identification Number which is specific to individual user.
firstName:
type: string
description: user's First name.
maxLength: 32
minLength: 1
pattern: ^[a-zA-Z\s]{1,32}$ ....
As you see, MyIdentity is not required in FooData however its property userID is marked as required.
Can we ignore the full MyIdentity object in the request body while hitting the API?
Assuming the request body schema is FooData:
Can we ignore the full MyIdentity object in the request body while hitting the API?
Yes - because the FooData.identity property is not required so it can be omitted. However, if the FooData.identity property is present, it must be an object and contain at least the userId property.
In other words, the following FooData payloads are valid:
{
"id": "abc",
"contact": "..."
}
{
"id": "abc",
"contact": "...",
"identity": {
"userId": 12345
}
}
but these payloads are invalid:
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {}
}
// No `userId` in `identity`
{
"id": "abc",
...,
"identity": {
"firstName": "Alex"
}
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": null
}
// `identity` is not an object
{
"id": "abc",
...,
"identity": "blah"
}

$ref in response example

The response example I would like to put in the yaml file is something like:
{
"name": "Element",
"schema": {
"properties": {
"id": {
"type": "string"
},
"extension": {
"type": "array",
"items": {
"$ref": "#/definitions/Extension"
}
}
}
}
}
And the ymal of this example will be:
responses:
200:
description: "successful operation, return the definition of the resource type in the body"
examples:
application/json:
name: Element
schema:
properties:
id:
type: string
extension:
type: array
items:
$ref: '#/definitions/Extension'
As you can see the last line is "$ref: '#/definitions/Extension'", thus Swagger thinks it is a reference which it can not find anywhere in the ymal file.
Is it possible to escape this to get way from being a reference?
This is a bug in Swagger Editor and UI.
As a workaround, define a schema for your response and use a schema example instead. Schema examples are displayed fine in Swagger Editor 3.6.6 and Swagger UI 3.17.5. You might still see a $ref resolution error in the editor, but at least the example is displayed correctly.
responses:
200:
description: "successful operation, return the definition of the resource type in the body"
schema:
$ref: '#/definitions/MyResponseSchema'
definitions:
MyResponseSchema:
type: object
properties:
name:
type: string
schema:
type: object
properties:
...
example: # <------------
name: Element
schema:
properties:
id:
type: string
extension:
type: array
items:
$ref: '#/definitions/Extension'

Define array of multiple models in Swagger 2.0

This is my first foray into Swagger so please be gentle.
I have the following definitions:
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
$ref: '#/definitions/Indicator'
Indicator:
type: object
properties:
type:
type: string
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
BBANDS:
properties:
type:
type: string
default: BBANDS
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
nbdevup:
type: integer
format: int32
default: 2
nbdevdn:
type: integer
format: int32
default: 2
matype:
type: integer
format: int32
default: 0
DEMA:
properties:
type:
type: string
default: DEMA
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
So Payload has a property called indicator which is an array of Indicators. The BBANDS and DEMA are models which are of type Indicator (which I know doesn't translate to Swagger). What I'd like to do is define an array of the actual models with their defaults, in this case BBANDS and DEMA. Something like this:
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
- '#/definitions/BBANDS'
- '#/definitions/DEMA'
or
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
- $ref '#/definitions/BBANDS'
- $ref '#/definitions/DEMA'
Neither of which work of course. The reason is while the Indicator model describes an indicator correctly, different indicators can have a different parameter set.
Is there a way to essentially define a list of several models or perhaps map the BBANDS and DEMA models into Indicator?
Edit: Result of using #Helen's first suggestion in the Swagger Editor
Swagger/OpenAPI 2.0 does not support multiple types for items, but there are a couple of ways to describe what you need.
Option 1 - Model Inheritance
As long as you have one field that is common between the models and can be used to distinguish between them, you can use model inheritance:
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#schemaDiscriminator
https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#composition-and-inheritance-polymorphism
In your example, this property is type (type="BBANDS" or type="DEMA"). So you can:
Inherit the BBANDS and DEMA models from Indicator by using allOf.
Add discriminator: type to Indicator to indicate that the type property will be used to distinguish between the sub-models.
Define Payload as an array of Indicator. This way it can actually be an array of BBANDS or an array of DEMA.
definitions:
Payload:
type: object
properties:
indicators:
type: array
items:
$ref: '#/definitions/Indicator'
Indicator:
type: object
properties:
type:
type: string
# Limit the possible values if needed
#enum:
# - BBANDS
# - DEMA
computeOn:
type: array
items:
type: string
default:
- close
# The "type" property will be used to distinguish between the sub-models.
# The value of the "type" property MUST be the schema name, that is, "BBANDS" or "DEMA".
# (Or in other words, the sub-model schema names must match possible values of "type".)
discriminator: type
required:
- type
BBANDS:
allOf:
- $ref: '#/definitions/Indicator'
- type: object
properties:
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
nbdevup:
type: integer
format: int32
default: 2
nbdevdn:
type: integer
format: int32
default: 2
matype:
type: integer
format: int32
default: 0
DEMA:
allOf:
- $ref: '#/definitions/Indicator'
- type: object
properties:
parameters:
type: object
properties:
timeperiod:
type: integer
format: int32
default: 5
Option 2 - Single Model
If all parameters are integer, you can have a single model Indicator with parameters defined as a hashmap. But in this case you lose the ability to define the exact parameters for specific indicator types.
definitions:
Indicator:
type: object
properties:
type:
type: string
enum:
- BBANDS
- DEMA
computeOn:
type: array
items:
type: string
default:
- close
parameters:
type: object
properties:
# This is a common parameter in both BBANDS and DEMA
timeperiod:
type: integer
format: int32
default: 5
# This will match additional parameters "nbdevup", "nbdevdn", "matype" in BBANDS
additionalProperties:
type: integer
AFAIK in array type can holds one type, if you want to have multiple types under an array, then need to define another super type and wrap the subtypes in it ( May be using object type ) like bellow. This restriction is because swagger-2.0 doesn't support all the features of json-schema.org, oneOf, anyOf, allOf etc are some of it.
But you can make use the third party extension option available with swagger-2.0. Where you can name a Key with x-, so that means you can include these oneOf like x-oneOf and when parsing the schema you do that using json-schema parser along with swagger schema parser.
One such example is given bellow,
Json-schema
{
"id": "http://some.site.somewhere/entry-schema#",
"$schema": "http://json-schema.org/draft-04/schema#",
"description": "schema for an fstab entry",
"type": "object",
"required": [
"storage"
],
"properties": {
"storage": {
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/diskDevice"
}
]
},
"deviceList": {
"type": "array",
"minItems": 1,
"items": {
"$ref": "#/definitions/Device"
}
}
},
"definitions": {
"diskDevice": {
"type": "object",
"properties": {
"label": {
"type": "string"
}
},
"required": [
"label"
]
},
"blockDevice": {
"type": "object",
"properties": {
"blockId": {
"type": "number"
}
},
"required": [
"blockId"
]
},
"CharDevice": {
"type": "object",
"properties": {
"charDeviceName": {
"type": "string"
}
},
"required": [
"charDeviceName"
]
},
"Device": {
"type": "object",
"oneOf": [
{
"$ref": "#/definitions/diskDevice"
},
{
"$ref": "#/definitions/blockDevice"
},
{
"$ref": "#/definitions/CharDevice"
}
]
}
}
}
Data or Payload
{
"storage": {"label": "adsf"},
"deviceList": [{"label": "asdf"}, {"blockId": 23}, {"charDeviceName": "asdf"}]
}
Use this site for play around with your sample data - http://www.jsonschemavalidator.net/
Note the deviceList property and how it got constructed. Hope this helps you.

How does swagger works with immutableMap (with different type of values) response?

I have some APIs which returns the following response. How can I use swagger to do the documentation? I know swagger responseContainer supports Map, but the value type of the map seems to have to be the same type. But in my case, the values are in different type: foos is type of List, and the second key "count" corresponds to integer.
Response.ok(ImmutableMap.of("result", foos, "count", foos.size())).build();
The response of the API is something like this:
{
"result": [
{
"f1": "v1",
"f2": "v2"
},
{
"f1": "v3",
"f2": "v4"
}
],
"count": 2
}
Your response can be described like this:
definitions:
MyResponse:
type: object
required:
- result
- count
properties:
result:
type: array
items:
$ref: '#/definitions/Foo'
count:
type: integer
Foo:
type: object
additionalProperties:
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