Specify an array of strings as body parameter in swagger API - rest

I would like to post an array of strings like
[
"id1",
"id2"
]
to a Swagger based API. In my swagger file, I have those lines:
paths:
/some_url:
post:
parameters:
- name: ids
in: body
required: true
What is the correct way to specify the type of ids as an array of strings?
Update:
According to the specification, the following should work in my option:
parameters:
- in: body
description: xxx
required: true
schema:
type: array
items:
type: string
https://github.com/Yelp/swagger_spec_validator does not accept it and returns a long list of convoluted errors, which look like the code expects some $ref.

Your description of an array of string is correct, but the parameter definition misses the name property to be valid.
Here's a full working example:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
responses:
default:
description: OK
Try the online editor to check your OpenAPI (fka. Swagger) specs: http://editor.swagger.io/

I have created a swagger issue as the help provided by Arnaud, although is valid yaml, will give you NPE exceptions when trying to generate. You will need to provide an object like the following:
myDataItem:
type: object
description: A list of values
required:
- values
properties:
values:
type: array
items:
type: string
And then refer to it (in your post item etc):
schema:
$ref: "#/definitions/myDataItem"
For reference the github issue:
https://github.com/swagger-api/swagger-codegen/issues/6745
Note, the issue has been fixed in version 2.3.0 and higher, ideally you should upgrade to that version.

None of the answers worked for me. As it is stated in the following Baeldung article:
To better document the API and instruct the user, we can use the example label of how to insert values
So the full working example would be something like that:
swagger: "2.0"
info:
title: A dummy title
version: 1.0.0
paths:
/path:
post:
parameters:
- in: body
description: xxx
required: true
name: a name
schema:
type: array
items:
type: string
example: ["str1", "str2", "str3"]
responses:
default:
description: OK
You can check how the Example Value is now better informed in the Swagger editor.

For Array containing Object as it's content, definition for Object can be also expressed using definitions & $ref.
Example:
schema:
type: array
items:
$ref: '#/definitions/ObjectSchemaDefinition'
definitions:
ObjectSchemaDefinition:
type: string

The answer with the most votes got me in the right direction. I just needed an example of an array of objects where each one of them had a property which was an array of strings with more than one value in the strings array. Thanks to the documentation I got it working like this:
MyObject:
type: object
properties:
body:
type: array
items:
type: object
properties:
type:
type: string
values:
type: array
items:
type: string
example:
- type: "firstElement"
values: ["Active", "Inactive"]
- type: "SecondElement"
values: ["Active", "Inactive"]
One thing to keep in mind is that indentation is of paramount importance to swagger. If you don't indent things well, swagger will give you strange error messages.

Related

Combining two choices in a single object

In my service schema I've got a single object that has two choices of properties. Meaning;
Object A needs: property 1 or 2, and property 3 or 4.
To realise this in OAS I'm using an object with an allOf property, which contains two items containing a oneOf property. I don't see a reason why this construction would be illegal. However, when using the swagger editor (https://editor.swagger.io/) and the Swagger Viewer extension in VSCode, it merges the two oneOf properties into a single one, effectively instructing the user to either include property 1, 2, 3 or 4.
One other way to achieve the same is to define a schema for every combination of choice 1 and 2, but this gets very tedious as the amount of options expands (effectively multiplying for every combination of the two choices).
Is my interpretation of the way this should work correct? If not, how can I achieve my goal without the spec becoming too verbose? If yes, I take it this is an issue in both tools I'm using, in that case I'll raise an issue in the respective issue trackers.
Example OAS spec:
openapi: 3.0.3
info:
description: Test API
version: 0.1.0
title: Test API
paths:
/test:
post:
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TestComplexObject'
responses:
'200':
description: OK
components:
schemas:
TestComplexObject:
type: object
allOf:
- type: object
properties:
defaultString:
type: string
- oneOf:
- $ref: '#/components/schemas/TestStr1'
- $ref: '#/components/schemas/TestStr2'
- oneOf:
- $ref: '#/components/schemas/TestStr3'
- $ref: '#/components/schemas/TestStr4'
TestStr1:
type: object
properties:
testString1:
type: string
required: [testString1]
TestStr2:
type: object
properties:
testString2:
type: string
required: [testString2]
TestStr3:
type: object
properties:
testString3:
type: string
required: [testString3]
TestStr4:
type: object
properties:
testString4:
type: string
required: [testString4]

Shall I use oneOf or multiple attributes on the same object for a component of OpenAPI specification?

In short, here's fragment of OpenAPI specification:
# Consider an imaginary Internet Service Provider that needs to limit
# one or multiple customers in different ways: bandwidth (inbound, outbound), media type (text / music / video), volume (total traffic volume, for example, 5 GB).
# per specific website (a user can have different limit for YouTube and Amazon).
# You'll likely want to rename some of the attributes but
#that's not the point (this API is fake and that's the best example I came up with to reproduce the issue).
components:
schemas:
ProviderLimit:
type: object
properties:
name:
type: string
website_id:
type: string
users:
type: array
items:
type: string
description: List of user IDs
minItems: 1
bandwidth:
type: object
$ref: '#/components/schemas/BandwidthLimit'
volume:
type: object
$ref: '#/components/schemas/VolumeLimit'
media:
type: string
enum:
- TEXT
- MUSIC
- VIDEO
BandwidthLimit:
properties:
incoming_speed:
type: string
format: int64
outcoming_speed:
type: string
format: int64
VolumeLimit:
properties:
target:
type: string
format: int64
The question is which approach shall I take:
Merge all the possible limits (bandwith, volume, media), make them all optional, and agree to specify just one of them on the client.
Use oneOf.
# Example of using oneOf
components:
schemas:
ProviderLimit:
type: object
properties:
name:
type: string
website_id:
type: string
users:
type: array
items:
type: string
description: List of user IDs
minItems: 1
limit_type:
type: object
oneOf:
- $ref: '#/components/schemas/BandwidthLimit'
- $ref: '#/components/schemas/VolumeLimit'
- $ref: '#/components/schemas/MediaLimit'
discriminator:
propertyName: type # or something else
It looks like option #2 looks a little bit better but overall one could tell #1 option is somewhat reasonable (it's very simple and doesn't overcomplicate the API). Is there a strong argument to use #2 besides it just looks a little bit better (for example, there's a use case where using #1 might not lead to expected results)?

OpenAPI 3: How to require one or more properties in PATCH requestBody?

I have a User resource:
I want to define a PATCH /users/{uid} so that the client can update image, bio or both.
An example valid request body would be:
{
"image": "filename.jpg",
"bio": "My biography"
}
If the image property is sent alone the existing bio property will remain the same on the server and only the image will be updated. If both are sent (as above) both will change.
In short:
an empty request body {} is disallowed.
{"image": "new.jpg"}, {"bio": "new bio" or {"image": "new.jpg", "bio": "new bio" is allowed.
This is what I have so far. I'm using the anyOf object with two separate type: objects within. I've tried this with Swagger hub using the virtserver, but the virtual server always seems to return 200 OK and passes back the example data regardless of whatever is passed, so I have no way to know.
Does my definition do what I intended? If not, what the best practice?
openapi: 3.0.0
...
patch:
summary: update a user
parameters:
- in: path
name: uid
description: user id
schema:
type: string
required: true
requestBody:
description: Update a user's profile
content:
application/json:
schema:
type: object
anyOf:
- type: object
properties:
image:
type: string
- type: object
properties:
bio:
type: string
additionalProperties: false
required: true
responses:
'200':
description: Successfully updated
content:
application/json:
schema:
$ref: '#/components/schemas/User'
You can use minProperties: 1:
requestBody:
description: Update a user's profile
content:
application/json:
schema:
type: object
properties:
image:
type: string
bio:
type: string
minProperties: 1 # <-----------
additionalProperties: false
or anyOf + required:
type: object
properties:
image:
type: string
bio:
type: string
anyOf: # <-----------
- required: [image]
- required: [bio]
additionalProperties: false
Your original example defines an empty object {} because:
Without required or minProperties defined, all properties are optional.
More importantly, additionalProperties: false only knows about the properties defined directly alongside it and has no visibility into subschemas. So, in this example it disallows ALL properties.
As for:
I've tried this with SwaggerHub using the VirtServer, but the virtual server always seems to return 200 OK and passes back the example data regardless of whatever is passed.
This is because SwaggerHub mocks do not validate inputs and always return a static response based on the response schema.
From SwaggerHub documentation:
Note that the mock does not support business logic, that is, it cannot send specific responses based on the input.
...
The mock generates static responses for each API operation based on its responses and the response media types defined in the spec.
If an operation has multiple response codes, the mock returns the response with the lowest status code. For example, if an operation has responses 201, 202 and 400, the mock returns the 201 response.

How to describe list of particular objects using Swagger in Spring Boot?

I described my controller using Swagger but when I tried to extract .yaml description of controller, as response of endpoints I found list of objects. How to make Swagger describe those list as list of particular objects such as list of cars, list of houses, list of animals, etc. and then to describe what particular object like car, house or animal is.
My case is:
/dummy_endpoint:
get:
tags:
- foo-controller
summary: Get foo list
description: Send GET request to obtain foo list
operationId: findAllFooUsingGET
produces:
- application/json
responses:
'200':
description: Foo list obtained successfully
schema:
type: array
items:
type: object
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Not Found
What I want to get:
/dummy_endpoint:
get:
tags:
- foo-controller
summary: Get foo list
description: Send GET request to obtain foo list
operationId: findAllFooUsingGET
produces:
- application/json
responses:
'200':
description: Foo list obtained successfully
schema:
type: array
items:
type: Foo
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
description: Not Found
definitions:
Foo:
type: object
properties:
id:
type: integer
format: int32
name:
type: String
I assume OpenAPI version 2.0 (based on the syntax in example). If you're using 3.0, let me know.
What you are looking for is ref. Check-in Swagger specification in section Input and Output Models and here in section Array and Multi-Value Parameters about arrays.
For example:
...
responses:
'200':
description: Foo list obtained successfully
schema:
type: array
items:
$ref: "#/definitions/Foo"
...
definitions:
Foo:
type: object
properties:
...
Thing that solved my problem was the usage of responseContainer property from #ResponseApi annotation, where I put type of response container like List, Array etc. and putting into response property type of objects that are stored into container.

How to specify the schema of a reusable request body parameter in OpenAPI 3.0

The swagger docs site shows an example for this case, but it does not follow through all the way to show the definition of the Pet schema.
E.g.:
paths:
/pets:
post:
summary: Add a new pet
requestBody:
$ref: '#/components/requestBodies/PetBody'
/pets/{petId}
put:
summary: Update a pet
parameters: [ ... ]
requestBody:
$ref: '#/components/requestBodies/PetBody'
components:
requestBodies:
PetBody:
description: A JSON object containing pet information
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/Pet'
I don't understand where the request body parameter names go in this scenario. I want to see the definition of #/components/schemas/Pet. For query parameters you have the components/parameters where you can define a name and a schema for each parameter. But I don't see the equivalent for the request body parameters. For example if I have a POST /api/pets with an application/json body of:
{ "name": "Fluffy", "type": "cat", "legs": 4 }
Where do I describe the parameters name, type and legs including their names?
Also on an unrelated topic it would be nice if there was a tag for OpenAPI v3.0 (not sure how to create one)
Also possible related question here.
After scouring the swagger docs I think I understand it now, I think the Pet schema would be:
components:
schemas:
Pet:
type: object
properties:
name:
type: string
type:
type: string
legs:
type: integer
required:
- type
I was missing out on the properties attribute.