swagger-api / swagger-core

Examples and server integrations for generating the Swagger API Specification, which enables easy access to your REST API

Home Page:http://swagger.io

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Could `@Schema(nullable = true)` work when outputting OpenAPI 3.1.0?

karlvr opened this issue · comments

Due to the removal of nullable: true from schema in 3.1.0, it appears that the nullable = 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 to Schema.getTypes:

    @OpenAPI31
    public Set<String> getTypes() {
        if (types != null) {
            if (nullable != null && nullable.booleanValue()) {
                Set<String> ss = new LinkedHashSet<>(types);
                ss.add("null");
                return ss;
            } else {
                return types;
            }
        } else {
            return null;
        }
    }

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!

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);
		}

	}
	
}