如何让OpenAPI Generator将Kotlin的Any类型生成为Any而非JsonObject?
问题核心
你当前的问题是:Kotlin DTO里的Map<String, Any>字段,生成OpenAPI规范时被限定为additionalProperties: {"type": "object"},导致OpenAPI Generator输出Map<String, JsonObject>,使用起来需要额外转换,且Jackson转换报错。
解决方案
1. 修正OpenAPI规范定义
首先要让OpenAPI规范正确反映Map<String, Any>的语义——值可以是任意JSON类型(字符串、数字、布尔、对象、数组、null),而不是仅允许对象类型。
将原来的spec片段:
"payload": { "type": "object", "additionalProperties": { "type": "object" } }
修改为以下两种方式之一:
- 简洁版(允许任意类型):
"payload": { "type": "object", "additionalProperties": true }
- 明确版(枚举所有支持的类型):
"payload": { "type": "object", "additionalProperties": { "anyOf": [ {"type": "string"}, {"type": "number"}, {"type": "integer"}, {"type": "boolean"}, {"type": "object"}, {"type": "array"}, {"type": "null"} ] } }
2. 调整OpenAPI Generator配置
针对Kotlin + kotlinx.serialization的场景,需要配置生成器将任意类型映射为更通用的类型,而非JsonObject:
- 使用命令行时添加参数:
openapi-generator-cli generate \ -i openapi-spec.json \ -g kotlin \ --additional-properties=serializationLibrary=kotlinx_serialization,mapAnyToJsonElement=false
- 或者用配置文件(如
config.yaml):
generatorName: kotlin additionalProperties: serializationLibrary: kotlinx_serialization mapAnyToJsonElement: false
这样生成的类会变成:
@Serializable public data class EventPayloadDto( @SerialName(value = "payload") val payload: kotlin.collections.Map<kotlin.String, Any>? = null, )
3. 从Kotlin代码生成规范时的注解调整
如果你的OpenAPI规范是从Kotlin代码自动生成的(比如用SpringDoc、Ktor OpenAPI插件),给payload字段添加注解来控制生成的spec:
import io.swagger.v3.oas.annotations.media.Schema data class EventDto( @Schema(additionalProperties = true) val payload: Map<String, Any>, // ...其他字段 )
这会让生成的spec自动使用additionalProperties: true,避免被限定为仅对象类型。
4. 序列化/反序列化的正确姿势
不要混合使用Jackson和kotlinx.serialization,针对生成的Map<String, Any>或Map<String, JsonElement>,直接用kotlinx.serialization的API处理:
- 序列化:
import kotlinx.serialization.encodeToString import kotlinx.serialization.json.Json val payloadJson = Json.encodeToString(event.payload)
- 反序列化:
val payloadMap: Map<String, Any> = Json.decodeFromString(payloadJson)
如果需要更灵活的类型处理,也可以改用Map<String, JsonElement>作为DTO字段,它能直接兼容所有JSON类型,且kotlinx.serialization原生支持,不需要额外转换。
内容的提问来源于stack exchange,提问作者Lofalan

