swagger-core
swagger-core copied to clipboard
Maps that use enums as keys don't explicitly declare them in the resulting swagger def.
Bug Description
In some parts of my API I have Maps that use enums as keys, such as uploadedLanguages example below:
@Schema(name = "DocumentUploads", description = "Model that aggregates document metadata by uploaded languages")
data class DocumentUploads(var metadata: DocumentMetadata,
var uploadedLanguages: Map<MimeType, Set<LanguageCode>>)
@Schema(name = "MimeType", description = "Type of currently supported file types on Seller Center.", enumAsRef = true)
enum class MimeType(val mediaType: MediaType) {
PDF(MediaType.APPLICATION_PDF), HTML(MediaType(MediaType.APPLICATION_XHTML_XML, Charsets.UTF_8));
}
This generates the default "Map" spec where keys are not known and can vary.
"DocumentUploads": {
"type": "object",
"properties": {
"metadata": {
"$ref": "#/components/schemas/DocumentMetadata"
},
"uploadedLanguages": {
"type": "object",
"additionalProperties": {
"uniqueItems": true,
"type": "array",
"items": {
"$ref": "#/components/schemas/LanguageCode"
}
}
}
},
"description": "Model that aggregates document metadata by uploaded languages"
}
However, since I need the resulting definition to explicitly declare possible keys as properties, I had to resort to this hack where I declare a fake swagger object with explicit properties.
This is really bad since it's hacky, hard to maintain and actually forces the required array in the resulting definition which could lead to some issues if I reuse this object as a payload input for the API.
@Schema(name = "DocumentUploads", description = "Model that aggregates document metadata by uploaded languages")
data class DocumentUploads(var metadata: DocumentMetadata,
@field:Schema(implementation = LanguagesByMimeType::class) var uploadedLanguages: Map<MimeType, Set<LanguageCode>>)
// Dummy object only used by springdoc.
@Schema(name = "LanguagesByMimeType", description = "Shows languages by mime type")
data class LanguagesByMimeType(@field:Schema(name="PDF", nullable = false, required = false) var pdf: Set<LanguageCode>,
@field:Schema(name="HTML", nullable = false, required = false)var html: Set<LanguageCode>)
Resulting in:
"DocumentUploads": {
"required": ["metadata", "uploadedLanguages"],
"type": "object",
"properties": {
"metadata": {
"$ref": "#/components/schemas/DocumentMetadata"
},
"uploadedLanguages": {
"$ref": "#/components/schemas/LanguagesByMimeType"
}
},
"description": "Model that aggregates document metadata by uploaded languages"
}
"LanguagesByMimeType": {
"required": ["HTML", "PDF"],
"type": "object",
"properties": {
"PDF": {
"uniqueItems": true,
"type": "array",
"items": {
"$ref": "#/components/schemas/LanguageCode"
}
},
"HTML": {
"uniqueItems": true,
"type": "array",
"items": {
"$ref": "#/components/schemas/LanguageCode"
}
}
},
"description": "Shows languages by mime type"
}
As a side note, this hack also has a bug. If I declare properties as upper-case as expected by the enum (eg. var PDF: Set<LanguageCode>) the resulting definition duplicates properties for some reason - camelcase and uppercase.
Proposed Solution
I would like to propose an alternative to handle such situations. It's understandable that springdoc can't automatically inspect map keys and determine if they're enums. But we could similarly help springdoc lib in figuring this part out via this sample property in @Schema:
@Schema(name = "DocumentUploads", description = "Model that aggregates document metadata by uploaded languages")
data class DocumentUploads(var metadata: DocumentMetadata,
@field:Schema(enumMap=true) var uploadedLanguages: Map<MimeType, Set<LanguageCode>>)
Resulting in:
"DocumentUploads": {
"required": ["metadata", "uploadedLanguages"],
"type": "object",
"properties": {
"metadata": {
"$ref": "#/components/schemas/DocumentMetadata"
},
"uploadedLanguages": {
"type": "object",
"properties": {
"PDF": {
"uniqueItems": true,
"type": "array",
"items": {
"$ref": "#/components/schemas/LanguageCode"
}
},
"HTML": {
"uniqueItems": true,
"type": "array",
"items": {
"$ref": "#/components/schemas/LanguageCode"
}
}
}
}
},
"description": "Model that aggregates document metadata by uploaded languages"
}
The enumMap flag that provides this hint could be using in conjunction with requiredProperties for handling some requirements of the resulting object (eg. imagine you use this map payload as an input and you always expect "PDF" to be present in the map).
bump
any updates on this?
any update?
We also are getting into this. Please SWAGGER TEAM, the issue has been properly reported, give us our daily portion of hope :-)
Will we get this in 2023?
Any chance to get it in 2024?