首页 文章

kotlin:不能用 Jackson 解析字符串

提问于
浏览
-1

我使用lib jackson-module-kotlin将json字符串解析为object .

我的问题是当我将字符串解析为枚举时,当我使用intellij启动时,我有这个堆栈跟踪:

引起:kotlin.reflect.jvm.internal.KotlinReflectionInternalError:尚未完全支持对内置Kotlin类型的反思 . 找不到公共最终val名称的元数据:kotlin.Enum中定义的kotlin.String [DeserializedPropertyDescriptor @ 212b316a]

当我使用maven启动时,我没有这个问题 .

我使用kotlin 1.1.51,使用intellij kotlin插件1.2.0-release-IJ2017.3-1,我的目标是JVM 1.8,我使用的是jackson-module-kotlin版本2.8.7

我该怎么办?

enum class CType { DEAL, FILE }
 data class Code(val code: String, val type: CType)

 fun testDeserialization() {
    val mapper = jacksonObjectMapper()
    // following line throws an exception:
    mapper.readValue("""{"code":"A","type":"DEAL"}""", Code::class.java)
 }

3 回答

  • 0

    Intellij最有可能使用kotlin编译器版本1.2.0(来自插件),它似乎不能正确支持反射 .

    我建议你做以下其中一项:

    • 将maven和intellij kotlin插件中的kotlin版本升级到更新版本(例如1.2.30) . 如果你这样做,你还必须将jackson-module-kotlin更新为> = 1.9,因为与kotlin 1.2不兼容(见here) .

    • 在Intellij Idea设置中将kotlin编译器版本设置为1.1 .

    在Intellij Idea和maven / gradle中使用相同版本的kotlin通常是个好主意 .

  • 0

    你需要使用与Kotlin 1.2.x兼容的Jackson的Kotlin模块,这包括这三个版本的模块:

    • 2.9.4.1 (适用于任何2.9.x的 Jackson ,但最好最近使用)

    • 2.8.11.1 ( Jackson 2.8.x)

    • 2.7.9.1 ( Jackson 2.7.x)

    否则,您将遇到库不匹配的问题 .

    jackson-module-kotlin homepage将这些列为当前版本,但它们可能会更改,您可以检查各种Maven存储库搜索引擎,以查看哪些库版本可用以及它们在Kotlin上具有哪些依赖关系以查找匹配版本 .

    另请注意,您可以导入 ObjectMapper 类的扩展名并使用已知类型,因此不是:

    val something = mapper.readValue("""{"code":"A","type":"DEAL"}""", Code::class.java)
    

    你将会拥有:

    val something: Code = mapper.readValue("""{"code":"A","type":"DEAL"}""")
    

    或者:

    val something = mapper.readValue<Code>("""{"code":"A","type":"DEAL"}""")
    

    使用擦除类型(即 Whatever::class.java )通常很糟糕,因为这对于具有泛型类型参数的任何内容都不起作用,并且使用reified类型在反序列化为集合时也可以很好地工作 .

  • 0

    你必须做一些事情 .

    Jackson 依赖项更新为最新版本(现在,2.9.4) . 将 Kotlin 版本更新为等于或大于1.3.0的版本 .

    确保将以下依赖项添加到build.gradle:

    implementation "org.jetbrains.kotlin:kotlin-reflect:$kotlin_version"
    implementation "com.fasterxml.jackson.module:jackson-module-kotlin:$jackson_version"
    

    ...然后你在 Jackson ObjectMapper 上调用 registerKotlinModule() ,你的枚举代码应该是这样的:

    enum class CType(@get:JsonValue val value: String) {
        DEAL("deal"),
        FILE("file");
    
        companion object {
    
            @JsonCreator
            fun fromString(value: String): CType? {
                for (type in CType.values()) {
                    if (type.name.equals(value, true)) {
                        return gender
                    }
                }
                return null
            }
        }
    }
    

相关问题