diff --git a/springdoc-openapi-starter-common-mcp/src/main/java/org/springdoc/ai/mcp/OpenApiSchemaConverter.java b/springdoc-openapi-starter-common-mcp/src/main/java/org/springdoc/ai/mcp/OpenApiSchemaConverter.java index 844f9f8fb..800f70daf 100644 --- a/springdoc-openapi-starter-common-mcp/src/main/java/org/springdoc/ai/mcp/OpenApiSchemaConverter.java +++ b/springdoc-openapi-starter-common-mcp/src/main/java/org/springdoc/ai/mcp/OpenApiSchemaConverter.java @@ -293,7 +293,12 @@ private static void applySchemaContent(Schema schema, ObjectNode node, Compon // Type and nullable String type = getSchemaType(schema); - if (Boolean.TRUE.equals(schema.getNullable())) { + Set types = schema.getTypes(); + if (types != null && types.size() > 1) { + ArrayNode typeArray = node.putArray("type"); + types.forEach(typeArray::add); + } + else if (Boolean.TRUE.equals(schema.getNullable())) { ArrayNode typeArray = node.putArray("type"); typeArray.add(type != null ? type : "object"); typeArray.add("null"); diff --git a/springdoc-openapi-starter-common-mcp/src/test/java/org/springdoc/ai/mcp/OpenApiSchemaConverterTest.java b/springdoc-openapi-starter-common-mcp/src/test/java/org/springdoc/ai/mcp/OpenApiSchemaConverterTest.java index c91d2502d..01f968a4a 100644 --- a/springdoc-openapi-starter-common-mcp/src/test/java/org/springdoc/ai/mcp/OpenApiSchemaConverterTest.java +++ b/springdoc-openapi-starter-common-mcp/src/test/java/org/springdoc/ai/mcp/OpenApiSchemaConverterTest.java @@ -23,6 +23,7 @@ import tools.jackson.databind.JsonNode; import tools.jackson.databind.ObjectMapper; +import io.swagger.v3.core.util.Json31; import io.swagger.v3.oas.models.Components; import io.swagger.v3.oas.models.Operation; import io.swagger.v3.oas.models.media.Content; @@ -751,6 +752,41 @@ void testNullableHandling() throws Exception { assertThat(nicknameNode.get("type").get(1).asText()).isEqualTo("null"); } + /** + * Test that OpenAPI 3.1 request body properties retain every declared type. + * @throws Exception if JSON parsing fails + */ + @Test + void testOpenApi31TypeArraysInRequestBody() throws Exception { + Operation operation = Json31.mapper().readValue(""" + { + "requestBody": { + "content": { + "application/json": { + "schema": { + "type": "object", + "properties": { + "content": { "type": ["string", "null"] }, + "label": { "type": ["integer", "string"] } + } + } + } + } + } + } + """, Operation.class); + + String schemaJson = OpenApiSchemaConverter.buildInputSchema("/notes", operation, null); + JsonNode properties = objectMapper.readTree(schemaJson).at("/properties/body/properties"); + + assertThat(properties.at("/content/type").isArray()).isTrue(); + assertThat(properties.at("/content/type")).extracting(JsonNode::asText) + .containsExactlyInAnyOrder("string", "null"); + assertThat(properties.at("/label/type").isArray()).isTrue(); + assertThat(properties.at("/label/type")).extracting(JsonNode::asText) + .containsExactlyInAnyOrder("integer", "string"); + } + /** * Test that anyOf schemas produce a JSON Schema anyOf array in input schema. * @throws Exception if JSON parsing fails