swagger-core
swagger-core copied to clipboard
Trying to declare an ApiResponse of type Map<String, List<Object>> does not work
I'm using swagger-annotations-2.2.0. I have an API like this (VERSION A/B: one of these lines is commented out):
@RestController
@RequestMapping("/v1/examples")
@Tag(
name = "Examples",
description = "CRUD for Examples"
)
class AgentLabelsApi {
@Operation(
description = "Example",
responses = [
ApiResponse(responseCode = "200"),
ApiResponse(
responseCode = "400",
content = [Content(additionalPropertiesSchema = Schema(implementation = Example::class), schema = Schema(additionalProperties = Schema.AdditionalPropertiesValue.TRUE))] // VERSION A
content = [Content(schema = Schema(implementation = MapOfStringToListOfExamples::class))] // VERSION B
)
]
)
@PostMapping
fun addExamples(
@SpringRequestBody
@RequestBody
examples: Map<String, List<Example>>
) = mapOf("someId" to listOf(Example("example")))
}
data class Example(
val name: String
)
abstract class MapOfStringToListOfExamples : Map<String, List<Example>>
I want to be able to express that for the 400 response, it returns a Map<String, List<Example>> using swagger/openapi annotations. Swagger knows what this should look like because it correctly formats it when I use this map type for the request body and on the function's return type. However, I can't seem to be able to express the same type when using the @Content and @Schema annotations. The above, with the one commented out line in place, is semantically wrong - I could not find a way to get @Schema itself to look like an array because the array prop is on @Content. But it also generates an even more confusing OpenAPI spec (abbreviated):
"400":
description: Bad Request
content:
'*/*':
schema:
type: string
additionalProperties: true
Huh? Where's my name prop?
This was Version A (where the line for Version B is commented out). Version B instead yields this OpenAPI spec (abbreviated):
responses:
"400":
description: Bad Request
content:
'*/*':
schema:
$ref: '#/components/schemas/MapOfStringToListOfExamples'
components:
schemas:
MapOfStringToListOfExamples:
type: object
properties:
size:
type: integer
format: int32
entries:
uniqueItems: true
type: array
items:
type: object
keys:
uniqueItems: true
type: array
items:
type: object
values:
type: array
items:
type: object
empty:
type: boolean
Huh? That's the accessor methods of Map<K, V>!
Is it possible to express, using Swagger annotations, that in the event of a 400 response, the response body will be Map<String, List<Example>>?
The real-life use case is that we have an API that needs to return a Map<String, List<ValidationError>> response if the user makes a mistake in filling out a form, where the map key is the field name, and each field can have more than one validation error. The actual request body and return value are different types.