使用接口反序列化Kotlin类时出现InvalidDefinitionException

时间:2019-07-16 16:07:05

标签: java kotlin jackson

我有几个实现此TypeAlias接口的Kotlin数据类:

import com.fasterxml.jackson.annotation.JsonValue;

public interface TypeAlias<T> {
    @JsonValue
    T getValue();
}

以前,我一直在使用早期版本的Jackson,并且对它们进行反序列化很好。但是现在我正在使用2.9.9。

一个无法反序列化的类:

data class UserId(@NotNull private val value: EntityId) : TypeAlias<EntityId> {
    @JsonCreator(mode = JsonCreator.Mode.DELEGATING)
    constructor(value: String) : this(EntityId(value))

    override fun getValue() = value
}

对此进行测试:

@Test
    fun `Deserialization test`() {
        val userIdString = "\"aaaaaaaaaaaaaaaaaaaaaa\""
        mapper.readValue(userIdString, UserId::class.java)
    } 

此测试会爆炸:

com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `UserId` (no Creators, like default construct, exist): no String-argument constructor/factory method to deserialize from String value ('aaaaaaaaaaaaaaaaaaaaaa')

我的映射器确实注册了KotlinModule。

请注意,UserId在其辅助String构造函数上确实有一个JsonCreator。该行为使我​​认为该接口导致Jackson看不到@JsonCreator批注。我在这里想念什么?

3 个答案:

答案 0 :(得分:1)

在与几个同事一起深入研究之后,我们意识到问题与在ObjectMapper上注册模块的顺序有关。我们在Kotlin模块之后注册了一个篡改配置的模块。相反,当我们在有问题的模块之后注册Kotlin模块时,一切又恢复了。

答案 1 :(得分:0)

我在下面的代码中使用了2.9.9,并且能够反序列化。 (很抱歉将其放在答案栏中,无法在评论部分中将其正确格式化)

data class abc( private val value: def?)  {

    @JsonCreator(mode =JsonCreator.Mode.DELEGATING)
    constructor( s: String) : this(def(s)) {
        println(s)
    }

}

data class def(val data: String)

fun main(args: Array<String>) {
    println("Hello World!")
    val m: ObjectMapper =  ObjectMapper()
    m.readValue("\"5abc\"", abc::class.java)
}

您可以将git链接发布到一个简单的仓库中,以便我们重现该问题吗?

答案 2 :(得分:0)

您需要一个有效的Jackson配置。看这个例子

@Configuration
class JacksonConfig {    
    @Bean
    fun objectMapper(): ObjectMapper {
        val objectMapper = ObjectMapper()    
        val jdk8Module = Jdk8Module().configureAbsentsAsNulls(true)
        objectMapper.registerModule(jdk8Module)
        objectMapper.registerModule(JavaTimeModule())
        // ... your customizations
        objectMapper.registerKotlinModule()
        return objectMapper
    }
}