Reputation: 853
How to specify a property as null or a reference? discusses how to specify a property as null or a reference using jsonschema.
I'm looking to do the same thing with swagger.
To recap the answer to the above, with jsonschema, one could do this:
{
"definitions": {
"Foo": {
# some complex object
}
},
"type": "object",
"properties": {
"foo": {
"oneOf": [
{"$ref": "#/definitions/Foo"},
{"type": "null"}
]
}
}
}
The key point to the answer was the use of oneOf
.
The key points to my question:
I have a complex object which I want to keep DRY so I put it in a definitions section for reuse throughout my swagger spec: values of other properties; response objects, etc.
In various places in my spec a property may be a reference to such an object OR be null.
How do I specify this with Swagger which doesn't support oneOf
or
anyOf
?
Note: some swagger implementations use x-nullable
(or some-such) to specify a property value can be null, however, $ref
replaces the object with what it references, so it would appear any use of x-nullable
is ignored.
Upvotes: 62
Views: 68405
Reputation: 23
I encountered a similar issue with OpenAPI 3.0, and the previously suggested solution didn't work for me:
foo:
nullable: true
allOf:
- $ref: '#/components/schemas/Foo'
I discovered an alternative solution using oneOf
to specify a nullable object without creating a separate nullable reference:
foo:
oneOf:
- type: object
nullable: true
- $ref: '#/components/schemas/Foo'
Upvotes: 0
Reputation: 131
I had a similar issue using Swashbuckle in a .net6 webAPI. I had a property that was an object but could also be nullable. It was failing to deserialize it when the object was null.
e.g. this worked and deserialized
{
"Foo":"bar"
"Details" {
"Test":"value",
"Test2":"value"
}
}
But this failed to deserialize
{
"Foo":"bar"
"Details": null
}
In order to fix the issue I added the following to my swagger setup.
builder.Services.AddSwaggerGen(options =>
{
options.UseAllOfToExtendReferenceSchemas();
});
Which generated the following
"someObject": {
"allOf": [
{
"$ref": "#/components/schemas/SomeObject"
}
],
"nullable": true
},
Upvotes: 3
Reputation: 1519
For OpenAPI 3.0 for some reason using nullable: true
followed by allOf
didn't work for the OpenAPI interpreter I'm using. As a workaround I ended up defining a must-be-null ref called null_type
that I can use in an anyOf
construct.
Like so:
allOf:
- anyOf:
- $ref: "#/components/schemas/null_type"
- $ref: "#/components/schemas/your_ref"
- description: "optionally add other properties here..."
where:
schemas:
null_type:
title: "OpenAPI 3.0 null-type ref"
description: "for adding nullability to a ref"
enum: [null]
your_ref:
...
Upvotes: 9
Reputation: 98022
Define the property as anyOf
of the $ref
and type: 'null'
.
YAML version:
foo:
anyOf:
- type: 'null' # Note the quotes around 'null'
- $ref: '#/components/schemas/Foo'
JSON version:
"foo": {
"anyOf": [
{ "type": "null" },
{ "$ref": "#/components/schemas/Foo" }
]
}
Why use anyOf
and not oneOf
? oneOf
will fail validation if the referenced schema itself allows nulls, whereas anyOf
will work.
YAML version:
foo:
nullable: true
allOf:
- $ref: '#/components/schemas/Foo'
JSON version:
"foo": {
"nullable": true,
"allOf": [
{ "$ref": "#/components/schemas/Foo" }
]
}
In OAS 3.0, wrapping $ref
into allOf
is needed to combine the $ref
with other keywords - because $ref
overwrites any sibling keywords. This is further discussed in the OpenAPI Specification repository: Reference objects don't combine well with “nullable”
Upvotes: 94
Reputation: 5441
Not easy to do that. Even almost impossible. Your options :
There is a very long discussion about this point, maybe one day it will be done...
You can use vendors extensions like x-oneOf and x-anyOf. I have already taken this hard way: You must to upgrade all used 'swagger tools' to take into account these vendors extensions.
In my case, we needed 'only' to :
It was a year ago, maybe now ...
Many projects don't need anyOf and oneOf, why not us ?
Upvotes: 5