-
-
Notifications
You must be signed in to change notification settings - Fork 558
Description
Describe the bug
When describing an inner record with a name that clashes with a package level record, the openapi description clashes both names and describe something that is not compatible with the API.
To Reproduce
Create a record name Data with an inner record named Value with a schema, then create a record at package level named Value with another schema. In the controller, return both com.example.springboot.Data and com.example.springboot.Value:
Records:
package com.example.springboot;
public record Value(String internalValue) {
}package com.example.springboot;
public record Data(String key, Value value) {
public record Value(String id, String value) {}
}Controller:
package com.example.springboot;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class HelloController {
@GetMapping("/data")
public Data data() {
return new Data("key", new Data.Value("id", "value"));
}
@GetMapping("/value")
public Value value() {
return new Value("this is a value");
}
}This repo was created to easily reproduce this problem https://github.com/jeffque/spring-doc-name-clash
Using:
-
spring-boot 4.0.0 (reproducible with 3.2.9)
-
springdoc-openapi 3.0.0 (reproducible with 2.5.0)
-
What is the actual and the expected result using OpenAPI Description (yml or json)?
Obtained openapi description:
{
"openapi": "3.1.0",
"info": {
"title": "OpenAPI definition",
"version": "v0"
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Generated server url"
}
],
"paths": {
"/value": {
"get": {
"tags": [
"hello-controller"
],
"operationId": "value",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Value"
}
}
}
}
}
}
},
"/data": {
"get": {
"tags": [
"hello-controller"
],
"operationId": "data",
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"$ref": "#/components/schemas/Data"
}
}
}
}
}
}
}
},
"components": {
"schemas": {
"Value": {
"type": "object",
"properties": {
"internalValue": {
"type": "string"
}
}
},
"Data": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"$ref": "#/components/schemas/Value"
}
}
}
}
}
}Expected behavior
The Value type description mentioned by the schema Data is pointing towards a description that is not compatible with the used type. What was expected was that it pointed towards another schema, for example:
{
...
"components": {
"schemas": {
"Value": {
"type": "object",
"properties": {
"internalValue": {
"type": "string"
}
}
},
"Data": {
"type": "object",
"properties": {
"key": {
"type": "string"
},
"value": {
"$ref": "#/components/schemas/Data.Value"
}
}
},
"Data.Value": {
"type": "object",
"properties": {
"id": {
"type": "string"
},
"value": {
"type": "string"
}
}
}
}
}
}This prevents name clash between the inner record com.example.springboot.Data.Value and the package level record com.example.springboot.Value.
This is not expected to occur only with records, but it should happen too with common classes.
Additional context
There are workarounds regarding this, like renaming the inner record in a way that its name does not clash with other classes. But this is intrusive and non-intuitive, sometimes the records are named in a way that is semantically accurate and renaming all the clashes is not ideal.