You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Kotlinx Serialization泛型数据类中使用@JsonNames解析多JSON字段名?

在Kotlinx Serialization泛型数据类中使用@JsonNames注解

结论

可以在泛型数据类中使用@JsonNames注解,你遇到的编译错误是kotlinx.serialization编译器插件的已知bug,通过升级依赖版本即可解决。

问题复现

普通数据类中正常使用@JsonNames的示例

@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class Project(@JsonNames("title") val name: String)

fun main() {
  val project = Json.decodeFromString<Project>("""{"name":"kotlinx.serialization"}""")
  println(project)
  val oldProject = Json.decodeFromString<Project>("""{"title":"kotlinx.coroutines"}""")
  println(oldProject)
}

输出:

Project(name=kotlinx.serialization)
Project(name=kotlinx.coroutines)

泛型数据类中的错误场景

泛型数据类代码:

@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class GoogleBaseApiResponse<T> (
    var status : String = "",
    var error_message : String? = null,
    @JsonNames("results", "predictions", "result") var responseData : T? = null
)

编译时抛出错误:

Exception in thread "main" java.lang.IllegalStateException: Problem with constructing exception message
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializerClassLowering.lower(SerializationLoweringExtension.kt:184)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:46)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:111)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.declarations.IrClass.acceptChildren(IrClass.kt:68)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptChildrenVoid(IrVisitors.kt:15)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:47)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitClass(IrElementVisitorVoid.kt:111)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitClass(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrClass.accept(IrClass.kt:64)
    at org.jetbrains.kotlin.ir.declarations.IrFile.acceptChildren(IrFile.kt:36)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptChildrenVoid(IrVisitors.kt:15)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitElement(SerializationLoweringExtension.kt:42)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitPackageFragment(IrElementVisitorVoid.kt:190)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitPackageFragment(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:200)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.visitors.IrElementVisitorVoid$DefaultImpls.visitFile(IrElementVisitorVoid.kt:198)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt$runOnFileInOrder$1.visitFile(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlin.ir.declarations.IrFile.accept(IrFile.kt:30)
    at org.jetbrains.kotlin.ir.visitors.IrVisitorsKt.acceptVoid(IrVisitors.kt:11)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtensionKt.runOnFileInOrder(SerializationLoweringExtension.kt:40)
    at org.jetbrains.kotlinx.serialization.compiler.extensions.SerializationLoweringExtension.generate(SerializationLoweringExtension.kt:149)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr$lambda$1(JvmIrCodegenFactory.kt:186)
    at org.jetbrains.kotlin.psi2ir.Psi2IrTranslator.generateModuleFragment(Psi2IrTranslator.kt:104)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:218)
    at org.jetbrains.kotlin.backend.jvm.JvmIrCodegenFactory.convertToIr(JvmIrCodegenFactory.kt:55)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.convertToIr(KotlinToJVMBytecodeCompiler.kt:225)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli(KotlinToJVMBytecodeCompiler.kt:102)
    at org.jetbrains.kotlin.cli.jvm.compiler.KotlinToJVMBytecodeCompiler.compileModules$cli$default(KotlinToJVMBytecodeCompiler.kt:47)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:167)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.doExecute(K2JVMCompiler.kt:53)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:101)
    at org.jetbrains.kotlin.cli.common.CLICompiler.execImpl(CLICompiler.kt:47)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:101)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:79)
    at org.jetbrains.kotlin.cli.common.CLITool.exec(CLITool.kt:43)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit(CLITool.kt:179)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMainNoExit$default(CLITool.kt:177)
    at org.jetbrains.kotlin.cli.common.CLITool$Companion.doMain(CLITool.kt:166)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler$Companion.main(K2JVMCompiler.kt:250)
    at org.jetbrains.kotlin.cli.jvm.K2JVMCompiler.main(K2JVMCompiler.kt)

解决方案

  1. 升级kotlinx.serialization版本:该bug在1.5.0及以上版本中已被修复,建议同步升级依赖和插件版本。示例Gradle配置:
    implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.5.0")
    kotlin("plugin.serialization") version "1.9.0"
    
  2. 临时替代方案(无法升级时):可自定义序列化器处理多字段名,或结合@SerialName与JsonBuilder.ignoreUnknownKeys实现解析,但这种方式繁琐,优先推荐版本升级。

修复后验证示例

升级版本后,泛型数据类可正常编译并解析不同字段名的JSON:

@OptIn(ExperimentalSerializationApi::class)
@Serializable
data class GoogleBaseApiResponse<T> (
    var status : String = "",
    var error_message : String? = null,
    @JsonNames("results", "predictions", "result") var responseData : T? = null
)

fun main() {
    val json1 = """{"status":"OK","results":[{"name":"test"}]}"""
    val response1 = Json.decodeFromString<GoogleBaseApiResponse<List<Map<String, String>>>>(json1)
    println(response1)

    val json2 = """{"status":"OK","predictions":[{"description":"test"}]}"""
    val response2 = Json.decodeFromString<GoogleBaseApiResponse<List<Map<String, String>>>>(json2)
    println(response2)

    val json3 = """{"status":"OK","result":{"id":1}}"""
    val response3 = Json.decodeFromString<GoogleBaseApiResponse<Map<String, Int>>>(json3)
    println(response3)
}

内容的提问来源于stack exchange,提问作者Suman Radhakrishnan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 13:30:55