I am trying to apply a custom Jackson deserializer (class "com.fasterxml.jackson.databind.JsonDeserializer") to a bean from a third-party library that requires custom deserialization. My custom deserializer is written in Kotlin:
@JsonComponent
class CustomDeserializer: JsonDeserializer<ThirdPartyBean> {
constructor(): super() {
println("CustomDeserializer registered")
}
override fun deserialize(parser: JsonParser?, context: DeserializationContext?): ThirdPartyBean? {
// Custom deserialization
}
override fun handledType(): Class<*> {
return ThirdPartyBean::class.java
}
}
I have tried to do all of the following (and in fact all combinations thereof):
Ad 2:
@JsonDeserialize(using = CustomDeserializer::class)
fun getThirdPartyBean(): ThirdPartyBean = thirdPartyBean
Ad 3:
@Bean
fun jacksonBuilder(): Jackson2ObjectMapperBuilder {
return Jackson2ObjectMapperBuilder()
.deserializers(CustomDeserializer())
}
Regardless of what I have tried, I always get this client-side error when attempting to serialize a bean that - among other properties - contains a property of type "ThirdPartyBean":
org.springframework.core.codec.CodecException: Type definition error: [simple type, class com.example.ThirdPartyBean]; nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.ThirdPartyBean` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
Spring Boot version is 2.3.1. I am at wits end on how to solve this, any help is appreciated.
I have managed to solve this on my own. However I'm pretty sure there must/should be a much simpler solution, so I'm happy to hear any suggestions. I solved the problem by manually registering a Jackson module that contains my CustomDeserializer in the WebClient setup:
@SpringBootApplication
@EnableWebFlux
class MyApplication: WebFluxConfigurer {
@Autowired
private lateinit var objectMapper: ObjectMapper
@Bean
fun webClient(): WebClient {
val customDeserializerModule = SimpleModule()
customDeserializerModule.addDeserializer(ThirdPartyBean::class.java, CustomDeserializer())
objectMapper.registerModule(customDeserializerModule)
return WebClient
.builder()
.codecs { it.defaultCodecs().jackson2JsonDecoder(Jackson2JsonDecoder(objectMapper)) }
.build()
}
}