required = schema.getRequired();
- if (required != null)
- required.replaceAll(name -> renames.getOrDefault(name, name));
- }
-
- /**
- * Returns the {@link ObjectMapper} of the active swagger-core {@code ModelResolver},
- * which is the mapper that applied (or did not apply) the naming strategy while
- * generating the schema.
- * @return the object mapper, or {@code null} if none could be located
- */
- private ObjectMapper resolverObjectMapper() {
- for (ModelConverter converter : ModelConverters.getInstance(springDocObjectMapper.isOpenapi31())
- .getConverters()) {
- if (converter instanceof ModelResolver modelResolver)
- return modelResolver.objectMapper();
- }
- return null;
- }
-
-}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SchemaUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SchemaUtils.java
index e4ad206d3..ff7a6d4e5 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SchemaUtils.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SchemaUtils.java
@@ -21,7 +21,6 @@
import com.fasterxml.jackson.annotation.JsonProperty;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.media.Schema.RequiredMode;
-import io.swagger.v3.oas.models.SpecVersion;
import io.swagger.v3.oas.models.media.Schema;
import jakarta.validation.OverridesAttribute;
import jakarta.validation.constraints.DecimalMax;
@@ -307,7 +306,6 @@ else if (OPENAPI_STRING_TYPE.equals(type)) {
schema.setMaximum(BigDecimal.valueOf(((Range) anno).max()));
}
});
- fixOAS31ExclusiveConstraints(schema);
if (schema!=null && annotatedNotNull(annotations)) {
String specVersion = schema.getSpecVersion().name();
if (!"V30".equals(specVersion)) {
@@ -576,28 +574,4 @@ private static JsonProperty getJsonProperty(Field f) {
if (g != null) return g.getAnnotation(JsonProperty.class);
return null;
}
-
- /**
- * Swagger-core 2.2.49 introduced so that {@link Positive} and {@link Negative} are introspected.
- * It does not correctly use the fact that exclusiveMinimum/exclusiveMaximum are values in OAS31.
- *
- * Tracked under swagger-core#5170.
- *
- * @param schema the schema to fix
- */
- public static void fixOAS31ExclusiveConstraints(Schema> schema) {
- if (schema == null) {
- return;
- }
- if (schema.getSpecVersion().equals(SpecVersion.V31)) {
- if (schema.getExclusiveMaximumValue() != null && schema.getMaximum() != null
- && schema.getMaximum().compareTo(schema.getExclusiveMaximumValue()) == 0) {
- schema.setMaximum(null);
- }
- if (schema.getExclusiveMinimumValue() != null && schema.getMinimum() != null &&
- schema.getMinimum().compareTo(schema.getExclusiveMinimumValue()) == 0) {
- schema.setMinimum(null);
- }
- }
- }
}
diff --git a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocUtils.java b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocUtils.java
index ae2fe78e6..594b95229 100644
--- a/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocUtils.java
+++ b/springdoc-openapi-starter-common/src/main/java/org/springdoc/core/utils/SpringDocUtils.java
@@ -31,7 +31,6 @@
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
import java.util.function.Predicate;
import com.fasterxml.jackson.core.type.TypeReference;
@@ -181,60 +180,9 @@ else if (schema.getItems() != null && schema.getItems().getType() != null
if (schema.getProperties() != null) {
schema.getProperties().forEach((key, value) -> handleSchemaTypes(value));
}
- fixNullOnlyAdditionalProperties(schema);
}
}
- /**
- * Fix additionalProperties incorrectly set to {"type": "null"} when @Nullable
- * propagates from a Map field to its Object value type (resolved as "any type" = {}).
- *
- * Tracked under swagger-core#5115.
- *
- * @param schema the schema to fix
- */
- public static void fixNullOnlyAdditionalProperties(Schema> schema) {
- if (schema == null) {
- return;
- }
- Object additionalProperties = schema.getAdditionalProperties();
- if (additionalProperties instanceof Schema> addPropSchema) {
- boolean isNullOnlyType = false;
- Set types = addPropSchema.getTypes();
- boolean onlyNullTypeOAS31 = types != null && types.size() == 1 && types.contains("null");
- boolean onlyNullTypeOAS30 = types == null && "null".equals(addPropSchema.getType());
- if (onlyNullTypeOAS31 || onlyNullTypeOAS30) {
- isNullOnlyType = true;
- }
- if (isNullOnlyType && addPropSchema.get$ref() == null
- && addPropSchema.getProperties() == null && addPropSchema.getFormat() == null) {
- addPropSchema.setTypes(null);
- addPropSchema.setType(null);
- }
- }
- if (schema.getProperties() != null) {
- schema.getProperties().values().forEach(SpringDocUtils::fixNullOnlyAdditionalProperties);
- }
- }
-
- /**
- * Removes {@code null}-keyed entries from a schema's properties map (and its nested
- * schemas). When swagger-core resolves a {@code @JsonUnwrapped} member (for example
- * Spring HATEOAS {@code EntityModel.getContent()} with HAL disabled), the unwrapped
- * property schemas may have a {@code null} name and get inserted into the properties map
- * under a {@code null} key. Such a key cannot be serialized by Jackson, which fails the
- * whole OpenAPI document with {@code "Null key for a Map not allowed in JSON"}.
- *
- * @param schema the schema to fix
- */
- public static void removeNullKeyProperties(Schema> schema) {
- if (schema == null || schema.getProperties() == null) {
- return;
- }
- schema.getProperties().keySet().removeIf(Objects::isNull);
- schema.getProperties().values().forEach(SpringDocUtils::removeNullKeyProperties);
- }
-
/**
* Handle schema types.
*
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/kotlin/test/org/springdoc/api/v31/app25/NullKeyController.kt b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/kotlin/test/org/springdoc/api/v31/app25/NullKeyController.kt
index 6419037a9..f273b1e9e 100644
--- a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/kotlin/test/org/springdoc/api/v31/app25/NullKeyController.kt
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/kotlin/test/org/springdoc/api/v31/app25/NullKeyController.kt
@@ -8,6 +8,8 @@ import org.springframework.web.bind.annotation.RestController
* Reproduces the swagger-core `@JsonUnwrapped` null-property-key issue: when the unwrapped
* member resolves to a `$ref` (a named component model), swagger-core adds a `null`-keyed
* entry to the enclosing schema properties, which breaks JSON serialization of the document.
+ *
+ * Fixed upstream by PR 5193
*/
@RestController
class NullKeyController {
diff --git a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/resources/results/3.1.0/app25.json b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/resources/results/3.1.0/app25.json
index 650dcae89..148a3c002 100644
--- a/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/resources/results/3.1.0/app25.json
+++ b/springdoc-openapi-tests/springdoc-openapi-kotlin-webmvc-tests/src/test/resources/results/3.1.0/app25.json
@@ -34,27 +34,41 @@
},
"components": {
"schemas": {
- "OuterResponse": {
- "type": "object",
- "properties": {
- "contractAddress": {
- "type": "string"
+ "NestedObject" : {
+ "type" : "object",
+ "properties" : {
+ "name" : {
+ "type" : "string"
},
- "chainType": {
- "type": "string",
- "enum": [
- "ETH"
- ]
+ "description" : {
+ "type" : [ "string", "null" ]
+ }
+ },
+ "required" : [ "name" ]
+ },
+ "OuterResponse" : {
+ "type" : "object",
+ "properties" : {
+ "contractAddress" : {
+ "type" : "string"
+ },
+ "chainType" : {
+ "type" : "string",
+ "enum" : [ "ETH" ]
+ },
+ "nested" : {
+ "type" : "null",
+ "oneOf" : [ {
+ "$ref" : "#/components/schemas/NestedObject"
+ }, {
+ "type" : "null"
+ } ]
},
- "success": {
- "type": "boolean"
+ "success" : {
+ "type" : "boolean"
}
},
- "required": [
- "chainType",
- "contractAddress",
- "success"
- ]
+ "required" : [ "chainType", "contractAddress", "success" ]
}
}
}