OpenApi v3: additionalProperties false with referenced schemas - swagger

There is some questions around this topic, but I dind't find the right way to do it.
What I want is to define all parameters in a single place and reuse it with no need to write it again. I already get that by using "allOf", but this limited the use of "additionalProperties".
My schema has this structure:
SchemaBase:
type: object
properties:
foo:
type: string
SchemaFull:
allOf:
- $ref: '#/components/schemas/SchemaBase'
- type: object
properties:
bar:
type: string
I tried using using definitions but it seems is not anymore in OpenApi version 3.
Here is a solution but its not what I'm looking for, becasue that is for properties, not the entire schema.

You need to use components like this:
openapi: 3.0.1
info:
title: OAS 3
version: 1.0.0
tags:
- name: example
paths:
/exe:
post:
requestBody:
content:
application/json:
schema:
additionalProperties: false
allOf:
- $ref: '#/components/schemas/SchemaBase'
- type: object
properties:
bar:
type: string
responses:
200:
description: Foo
content: {}
components:
schemas:
SchemaBase:
type: object
properties:
foo:
type: string
You may see and play with this here: https://editor.swagger.io/
JSON schema mapped:
{
"additionalProperties": false,
"allOf": [
{ "$ref": "#/definitions/SchemaBase" },
{
"type": "object",
"properties": {
"foo": {
"type": "string"
}
}
}
],
"definitions": {
"SchemaBase": {
"type": "object",
"properties": {
"foo": {
"type": "string"
}
}
}
}
}

Related

Swagger OpenAPI array documentation in response

How a Json like this be documented inside response section in swagger?
{
"data": [{
"id": "",
"name": "James",
"chat": "1",
"messages": {
"current": null,
"count": null,
"length": null,
"rows": null,
"type": null
},
"cid": "204",
"cat": "messages",
"mark": false
}],
"total": 200,
"action": "success"
}
I tried
responses:
'200':
description: test data
content:
application/json:
schema:
example:
- id: null
name: James
chat: 1
messages:
current:
count:
length:
rows:
type:
cid: 204
cat: chat
mark: false
totalCount: 200
action: success
But show error bad indentation of a mapping entry
You have to define the expected object structure as a separate schema in the #/components/schemas section.
For example you name the resulting model ResponseObj, which has the properties data, total and action. The data property is another complex type with its own properties, so you also define a model for that type. This continues until you have defined all the models down to their simple property types.
Here is the definition for your example:
components:
schemas:
ResponseObj:
properties:
data:
type: array
items:
$ref: '#/components/schemas/DataObj'
total:
type: string
action:
type: string
DataObj:
properties:
id:
type: string
name:
type: string
chat:
type: string
messages:
type: array
items:
$ref: '#/components/schemas/MessageObj'
cid:
type: number
cat:
type: string
mark:
type: boolean
MessageObj:
properties:
current:
type: string
count:
type: string
length:
type: number
rows:
type: number
type:
type: string
Now you can reference the ResponseObj model as the expected result of your operation:
paths:
/example:
get:
responses:
"200":
content:
application/json:
schema:
$ref: '#/components/schemas/ResponseObj'

Associative array in Swagger (OpenApi 3.0.0)

I have an API that always answers with an associative array where there is only one entry with key "data" containing the final result. The result can be an object or array of objects. This is API output:
{
"data": {
"id": 1,
"name": "product1 name",
"type": "type a",
"created_at": "2011-09-28T13:20:15+02:00"
}
}
{
"data": [
{
"id": 1,
"name": "product1 name",
"type": "type a",
"created_at": "2010-09-28T13:20:15+02:00"
},
{
"id": 6,
"name": "product6 name",
"type": "type f",
"created_at": "2010-09-28T13:20:28+02:00"
},
{
"id": 17,
"name": "product17 name",
"type": "type Q",
"created_at": "2010-09-28T13:20:42+02:00"
}
]
}
How can I get swagger to show data which is the name of the key, in the docs?
As for now I only get nested array in swagger:
[
{
"id": 1,
"name": "product1 name",
"type": "type a",
"created_at": "2010-09-28T13:20:15+02:00"
}
]
[
[
{
"id": 1,
"name": "product1 name",
"type": "type_a",
"created_at": "2010-01-01T18:21:20+02:00"
}
]
]
I need the data key to be shown in swagger as it comes back from the API. Is it doable? I wasn't able to find any solution to this yet...:/
parts of my yaml file:
openapi: "3.0.0"
info:
version: 1.0.0
paths:
/products/:
get:
summary: List all available products
operationId: listProducts
tags:
- products
responses:
200:
description: Array of products
content:
application/json:
schema:
type: array
items:
$ref: "#/components/schemas/Products"
/products/{product_id}:
get:
summary: Get specific product
operationId: showProductById
tags:
- products
parameters:
- name: product_id
in: path
required: true
description: The id of the product to retrieve
schema:
type: integer
format: int32
example: 1
responses:
200:
description: Product object
content:
application/json:
schema:
type: array
properties:
datar: string
items:
$ref: "#/components/schemas/Product"
components:
schemas:
Product:
type: object
properties:
id:
type: integer
format: int32
example: 10
name:
type: string
example: "producta name"
type:
type: string
example: "type a"
created_at:
type: string
format: date
example: "2010-01-01T18:21:20+02:00"
Products:
type: array
items:
$ref: "#/components/schemas/Product"
Any help will be much appreciated:)
Cheers
try with a "additionalProperties" in a intermediate layer for a assoc-array, source: https://swagger.io/docs/specification/data-models/dictionaries/
components:
schemas:
Product:
type: object
properties:
id:
type: integer
format: int32
example: 10
name:
type: string
example: "producta name"
type:
type: string
example: "type a"
created_at:
type: string
format: date
example: "2010-01-01T18:21:20+02:00"
ArrayOfProduct:
type: object
additionalProperties:
$ref: "#/components/schemas/Product"
Products:
type: object
properties:
data:
type: object
$ref: "#/components/schemas/ArrayOfProduct"

Swagger: Reuse schema definition inside object property

Problem: I want to reuse a definiton. Once directly and once inside an object. The following code works but the validator from http://editor.swagger.io/#/ is saying "Not a valid response definition" and pointing to the line "200".
Do I really have to define Account twice? Or is this an issue form the validator?
* responses:
* 200: <---- ERROR POINTING HERE
* description: Updated account
* schema:
* type: object
* properties:
* data:
* type: object
* properties:
* account:
* schema:
* $ref: '#/definitions/Account'
The definition itself:
"Account" : {
"type" : "object",
"required": [
"id", "username", "lastname", "firstname", "traderid", "customerid", "company", "validated"
],
"properties": {
"id": {
"type": "string"
},
"username" : {
"type": "string"
},
"lastname" : {
"type": "string"
},
"firstname" : {
"type": "string"
},
"traderid" : {
"type": "string"
},
"customerid" : {
"type": "string"
},
"company" : {
"type": "string"
},
"validated" : {
"type": "boolean"
}
},
"example" : {
"id": "57790fdde3fd3ed82681f39c",
"username": "yuhucebafu",
"validated": false,
"customerid": "57790fdce3fd3ed82681f39a"
}
},
The problem is with the use of schema in the account property.
200:
description: Updated account
schema:
type: object
properties:
data:
type: object
properties:
account:
schema: # <-- Problem is here.
$ref: '#/definitions/Account'
Here's the corrected response definition:
200:
description: Updated account
schema:
type: object
properties:
data:
type: object
properties:
account:
$ref: '#/definitions/Account'
The property name "schema" is only used as a top-level property in Swagger's response object, or a parameter object where in is set to "body".
Once you've started specifying your schema, everything within that structure mostly follows standard JSON Schema, which is highly recursive. For example:
Within an object schema, the value of each properties/[propertyName] is a schema.
Within an array schema, the value of items is a schema.
The value of each /definitions/[name] is a schema.
The value of each array element within allOf, anyOf, or oneOf is a schema.
The value of additionalProperties can be a schema (or a boolean value).
...
You get the idea. JSON Schema doesn't use the property name schema for all of these cases, because it would introduce a lot of noise in a language where practically "everything is a schema."

Model response containing array of different object types in swagger

I want to model a response object containing an array of different types of objects in swagger, something like this:
{
"table": [
{
"user" : []
},
{
"customer": []
},
{
"employee": []
}
]
}
I have tried a solution below but it wraps all the properties in a single object { [ { "user": [], "customer": [] } ] }.
responses:
200:
schema:
type: array
items:
type: object
properties:
user:
type: array
items:
$ref: '#/definitions/User'
customer:
type: array
items:
$ref: '#/definitions/Customer'
employee:
type: array
items:
$ref: '#/definitions/Employee'
That will be supported in the next release of OpenAPI spec (3.0) and here is the related discussion about this feature:
https://github.com/OAI/OpenAPI-Specification/issues/57
Here is an example (provided in the URL above):
{
"oneOf": [
{ "$ref": "Cat" },
{ "$ref": "Dog" }
]
}

Combining defintions in Swagger docs

I'm documenting an API with Swagger docs. I have several endpoints that share a common set of base properties. I'd like to use $ref to refer to that base set of properties and then extend those properties with additional properties that are unique to each endpoint. I imagined that it would work something like this, but this is invalid:
"properties": {
"$ref": "#/definitions/baseProperties",
unique_thing": {
"type": "string"
},
"another_unique_thing": {
"type": "string"
}
}
Indeed, the example you give here is invalid because $ref can't co-exist with other properties in the same object. $ref is a JSON Reference, and by definition, will cause the other properties to be ignored.
From your question, I assume you're looking for basic composition (rather than inheritance). This is achievable using the allOf keyword.
So, with the example you provided, you would have something like this:
{
"baseProperties": {
"type": "object",
"properties": {
...
}
},
"complexModel": {
"allOf": [
{
"$ref": "#/definitions/baseProperties"
},
{
"type": "object",
"properties": {
"unique_thing": {
"type": "string"
},
"another_unique_thing": {
"type": "string"
}
}
}
]
}
}
YAML version:
definitions:
baseProperties:
type: object
properties:
...
complexModel:
allOf:
- $ref: '#/definitions/baseProperties'
- type: object
properties:
unique_thing:
type: string
another_unique_thing:
type: string
You can also check out the example in the spec.

Resources