OpenAPI optional object default value - openapi

Suppose you have the following OpenAPI requestBody specification:
requestBody:
required: true
content:
application/json:
schema:
type: object
properties:
field1:
type: number
default: 1
field2:
type: object
properties:
subfield:
type: number
default: 2
The request body contains:
a number field with default value 1
an object field, containing itself a number field with default value 2
If a client sends an empty payload, we should agree that field1 value is supposed to be 1, but what about field2 value?
field2 is not specified, so it must be considered as null
field2 should be an object build with default values: {subfield: 2}
OpenAPI does not answer this question and that's up to me to decide what my application should do

Correct behaviour would be your alternative 1, with a twist.
field2 should be considered to be "not present" and not null as there is some difference between those cases, see https://github.com/OAI/OpenAPI-Specification/issues/1775 for some discussion related to that difference.
From a validation point-of-view field2 is not declared as nullable an object like {"field2": null} should not be valid, but {} would be.
Whether "not present" or null should be handled differently is up to your application.

Related

Why are the OpenAPI 3 oneOf example objects not always valid against both schemas

The specification for the oneOf keyword in https://swagger.io/docs/specification/data-models/oneof-anyof-allof-not/#oneof has an example schema as well as three example objects. The request body is oneOf the Dog or Cat schema:
Dog:
type: object
properties:
bark:
type: boolean
breed:
type: string
enum: [Dingo, Husky, Retriever, Shepherd]
Cat:
type: object
properties:
hunts:
type: boolean
age:
type: integer
And the three JSON objects:
Object 1
{
"bark": true,
"breed": "Dingo"
}
Object 2
{
"bark": true,
"hunts": true
}
Object 3
{
"bark": true,
"hunts": true,
"breed": "Husky",
"age": 3
}
They say, the first object is valid against one of the schemas (I assume they mean the Dog schema), the second one is not valid against both schemas and the third is valid against both schemas. This means the second and third object are not correct request bodies.
But why are not all three objects valid against both schemas? None of the keywords for objects mentioned here http://json-schema.org/draft/2020-12/json-schema-validation.html#name-validation-keywords-for-obj are used. And the types of the properties match for all the objects.
I played with this validator https://www.jsonschemavalidator.net/ and wrote also a simple schema with an object with some properties and even an empty json validates against the schema.
It seems that my assumptions are correct and all objects are valid against the oneOf schema. I found an issue reporting this: https://github.com/swagger-api/swagger.io/issues/253.

How to define a header parameter with multiple attributes in OpenAPI 3.0?

I need to define a header parameter like this X-Custom: id1=uuid1;id2=uuid3
Since this is a common header for all paths I want to define it once and reference it every time. So far I came up with this:
openapi: 3.0.3
components:
parameters:
customHeader:
name: "X-Custom"
in: header # <--- produces error
required: true
schema:
type: object
properties:
id1:
type: string
format: uuid
id2:
type: string
format: uuid
style: matrix
explode: true
But I get an error that 'header' is not allowed and the parameter does not show up in the preview.
Any idea what's wrong?
OpenAPI 3 supports only style: simple for header parameters. This means that objects can be serialized in one of two ways:
# {"id1": "uuid1", "id2": "uuid2"} becomes...
# explode: false
X-Custom: id1,uuid1,id2,uuid2
# explode: true
X-Custom: id1=uuid1,id2=uuid2
Note that none of these styles match your expected format X-Custom: id1=uuid1;id2=uuid2 with ; as a separator. In fact, OpenAPI currently does not have a way to define ;-separated header values.
The most you can do is define the entire header as a string, mention the header value format in the description, and provide an example value:
customHeader:
name: X-Custom
in: header
required: true
schema:
type: string
example: id1=uuid1;id2=uuid2
There are existing feature requests to improve header serialization styles in OpenAPI:
Support for structured-headers de/serialization
Make it easier to define link headers
If you are designing a new API rather than documenting an existing one, another workaround is to split the header into two headers:
X-id1: uuid1
X-id2: uuid2

How to specify an unknown number of a parameter in the response Open API

I'm trying to model my API using swagger and the Open API 3.0 specification. I have made some schemas and now I'm modeling the response of my endpoints. The problem is that they return something like this:
[
{
"name": "this attribute is always here"
"type1": { "description": "this maybe appear or not" },
"type2": { "description": "this maybe appear or not" },
...
"typeN": { "description": "N is not a fixed number, it may range from 0 to another positive integer" },
}
]
I know how to model the array and the object (with the name property). The problem comes when I have to model the typeX properties, I do not know how to specify that they are optional and the number of ocurrences is variable. Any idea?
This object is basically a string-to-object dictionary/hashmap with an extra name property. Fixed properties are defined in properties, and the dictionary part can be defined using either patternProperties (in OpenAPI 3.1) or additionalProperties (in OpenAPI 3.0 and 2.0).
OpenAPI 3.1
In OAS 3.1 your object can be defined as follows. Since the optional property names all follow the typeX format, the schema uses patternProperties to define the regex for the property names.
MyObject:
type: object
required: [name]
properties:
name:
type: string
patternProperties: # <-- This part defines the "typeX" properties
^type\d+$: # <-- Property name regex
type: object # <-- Property value
properties:
description:
type: string
additionalProperties: false # No other properties other than "name" and "typeX"
OpenAPI 3.0 and 2.0
In earlier OAS versions, you use additionalProperties to define "may have extra properties with <such> values", but there's no way to define the format of those property names. You can however mention the property name format in the schema description and also add a schema example for documentation purposes.
MyObject:
type: object
description: >-
In addition to the `name` property, this object may have an arbitrary
number of properties named `typeX` where X is a positive integer.
required: [name]
properties:
name:
type: string
additionalProperties:
# This part defines the *value* of the typeX properties
type: object
properties:
description:
type: string
# Optional schema example
name: something
type1:
description: ....
type2:
description: ....

Define Kubernetes Custom Resource requiring one of the following fields or no fields

I try to define a new Custom Resource, requiring it to have one of (1) field A, (2) field B, or (3) empty body.
For example: {A: 1}, {B: 1}, {} are OK, but {A:1, B:2} is not.
Here is the definition of my Custom Resource in form of OpenApi schema:
foo:
type: object
properties:
a:
type: int
b:
type: int
oneOf:
- required: ["a"]
- required: ["b"]
# no sure how to include the empty body
How should I include the empty body in the oneOf constraint?
OpenAPI 3.1
You can use 'null' (with quotes).
oneOf:
- type: 'null'
Or an object with a property of type null.
oneOf:
- NullObjectExample:
type: object
properties:
prop1:
type: 'null'
OpenAPI 3.0
There is no null type, but you can use a nullable string. You may want to add a description stating this is expected to be null at all times.
oneOf:
- type: string
nullable: true
Or again, an object with a nullable string property.
oneOf:
- NullObjectExample:
type: object
properties:
prop1:
type: string
nullable: true
Why No Empty Object
In addition to not making intent clear, this presents a possible security vulnerability. See this page for an explanation. In short:
If you do not clearly define the schema and you leave properties of a JSON payload empty, you effectively allow attackers to pass in any data. This means that you are opening your backend to various attacks, such as SQL injection.

how to add a value to a swagger element?

Hi Am trying to update some api swagger documentation and i want to add values to the keys rather than having only the type displayed
e.g
isGuaranteed:
type: boolean
value : true
name:
type: string
value :John
is the anyway to add a tag value rather than having only the type ?
You can provide example value by adding example and a value to a property definition:
isGuaranteed:
type: boolean
example: true
name:
type: string
example :John
Rendering in Swagger UI: