Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

InvalidDefinitionException when deserializing Kotlin class with interface

I have several Kotlin data classes that implement this TypeAlias interface:

import com.fasterxml.jackson.annotation.JsonValue;

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

Previously, I'd been using an earlier version of Jackson and they deserialized fine. But now I'm using 2.9.9.

One class that fails to deserialize:

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 for it:

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

This test blows up with:

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')

My mapper does have the KotlinModule registered.

Note that UserId does have a JsonCreator on its secondary String constructor. The behavior makes me think that the interface is causing Jackson to not see the @JsonCreator annotation. What am I missing here?

like image 971
davidmerrick Avatar asked Oct 19 '25 01:10

davidmerrick


1 Answers

You need a valid Jackson config. Take a look at this example

@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
    }
}
like image 95
naXa Avatar answered Oct 20 '25 15:10

naXa