Open karlvr opened 1 year ago
Ugh, nullable
properties that use a $ref
aren't that simple... it seems they need to transform into:
allOf:
- $ref: '#/...'
- { type: "null" }
Heh, I'm not immediately a fan of OpenAPI 3.1 :-D
Instead I've solved this with a filter. If you, the maintainers, think that support for Schema.nullable
is nice for OpenAPI 3.1 support, I'd be happy to work on a PR, otherwise I'll leave this filter here for anyone else in this predicament to enjoy and please close this issue!
import java.util.List;
import java.util.Map;
import java.util.Optional;
import io.swagger.v3.core.filter.AbstractSpecFilter;
import io.swagger.v3.core.util.AnnotationsUtils;
import io.swagger.v3.oas.models.SpecVersion;
import io.swagger.v3.oas.models.media.Schema;
/**
* A filter to add support for {@link Schema#getNullable()} under OpenAPI 3.1.0. As of swagger-core 2.2.19 that property
* is ignored when serializing to OpenAPI 3.1.0. This filter modifies property schemas to translate nullable to
* OpenAPI 3.1.0.
* <p>
* OpenAPI 3.1.0 doesn't directly support {@code nullable} anymore; instead we must add {@code null} to the array of types.
*/
public class NullableToOpenAPI31Filter extends AbstractSpecFilter {
@Override
public Optional<Schema> filterSchemaProperty(Schema property, Schema schema, String propName,
Map<String, List<String>> params, Map<String, String> cookies, Map<String, List<String>> headers) {
if (property.getNullable() != null && property.getNullable().booleanValue()) {
if (property.get$ref() != null) {
Schema clone = AnnotationsUtils.clone(property, isOpenAPI31Filter());
clone.$ref(null);
clone.addAnyOfItem(new Schema(property.getSpecVersion()).$ref(property.get$ref()));
clone.addAnyOfItem(new NullSchema(property.getSpecVersion()));
return Optional.of(clone);
} else {
Schema clone = AnnotationsUtils.clone(property, isOpenAPI31Filter());
if (!clone.getTypes().contains("null")) {
clone.addType("null");
}
return Optional.of(clone);
}
} else {
return super.filterSchemaProperty(property, schema, propName, params, cookies, headers);
}
}
@Override
public boolean isOpenAPI31Filter() {
return true;
}
public static class NullSchema extends Schema {
public NullSchema(SpecVersion specVersion) {
super("null", null, specVersion);
}
}
}
@karlvr how do you apply this filter?
@zeldigas sorry for the slow reply, like this in my class that extends javax.ws.rs.core.Application
:
OpenAPI oas = new OpenAPI();
...
SwaggerConfiguration oasConfig = new SwaggerConfiguration();
oasConfig.setOpenAPI(oas);
oasConfig.openAPI31(true); /* Required so that descriptions on properties that turn into $refs stay on the property */
oasConfig.setFilterClass(NullableToOpenAPI31Filter.class.getName());
try {
new JaxrsOpenApiContextBuilder()
.servletConfig(servletConfig)
.application(this)
.openApiConfiguration(oasConfig)
.buildContext(true);
} catch (OpenApiConfigurationException e) {
throw new RuntimeException(e.getMessage(), e);
}
Due to the removal of
nullable: true
from schema in 3.1.0, it appears that thenullable = true
property on the@Schema
annotation no longer works. That isn't obvious in the documentation for the annotation, and it's inconvenient to boot ;-)I think it will be quite easy to continue to support the
nullable
attribute under 3.1.0, I suggest a little change toSchema.getTypes
:We simply add
"null"
to the list of types if the schema is nullable... which ends up nicely in the schema output.I'm happy to make a PR of this, or a better suggestion, or I'd love to know if this is more like the wrong approach!