spring-bootjacksondeserializationspring-webfluxjson-deserialization

Spring Boot - Custom JsonDeserializer is ignored


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

  1. Use the class as-is: I can see that the deserializer is picked up - I can see the "CustomSerializer registered" being printed.
  2. Annotate the field that uses the ThirdPartyBean with the custom deserializer (see below)
  3. Explicitly register the Deserializer with the ApplicationContext (see below)

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.


Solution

  • 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()
            }
        }