我正在尝试将自定义 Jackson 反序列化器(类“com.fasterxml.jackson.databind.JsonDeserializer”)应用到需要自定义反序列化的第三方库中的 bean。我的自定义反序列化器是用 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
}
}
我已尝试执行以下所有操作(实际上是其所有组合):
广告2:
@JsonDeserialize(using = CustomDeserializer::class)
fun getThirdPartyBean(): ThirdPartyBean = thirdPartyBean
广告3:
@Bean
fun jacksonBuilder(): Jackson2ObjectMapperBuilder {
return Jackson2ObjectMapperBuilder()
.deserializers(CustomDeserializer())
}
无论我尝试过什么,在尝试序列化包含“ThirdPartyBean”类型的属性的 bean(以及其他属性)时,我总是会收到此客户端错误:
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 版本是 2.3.1。我对如何解决这个问题束手无策,感谢任何帮助。
我已经自己解决了这个问题。不过我很确定必须/应该有一个更简单的解决方案,所以我很高兴听到任何建议。我通过在 WebClient 设置中手动注册包含我的 CustomDeserializer 的 Jackson 模块解决了该问题:
@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()
}
}
抱歉,我的答案将是用 Java 语言,因为我刚刚为自己解决了同样的问题
问题在于您如何注册模块。如果您查看
JsonComponentModule
类,您会发现它使用以下
@Override
public void afterPropertiesSet() {
registerJsonComponents();
}
public void registerJsonComponents() {
BeanFactory beanFactory = this.beanFactory;
while (beanFactory != null) {
if (beanFactory instanceof ListableBeanFactory listableBeanFactory) {
addJsonBeans(listableBeanFactory);
}
beanFactory = (beanFactory instanceof HierarchicalBeanFactory hierarchicalBeanFactory)
? hierarchicalBeanFactory.getParentBeanFactory() : null;
}
}
这是创建反序列化器的时候。这种情况恰好发生在配置 bean 之后,因此创建
new JsonComponentModule()
会破坏这种情况。它永远不会融入豆子中。
为了使这项工作顺利进行,您有两种选择。如果 Spring 使用 Jackson 自动配置,那么您需要在 spring 提供的已配置的
JsonComponentModule
bean 中进行自动装配,例如
@Bean
public ObjectMapper objectMapper(JsonComponentModule jsonComponentModule){
return new ObjectMapper()
.registerModule(jsonComponentModule);
}
如果没有,那么您首先需要创建
JsonComponentModule
bean。例如
@Bean
public JsonComponentModule jsonComponentModule() {
return new JsonComponentModule();
}
然后将其自动连接到您的对象映射器创建中。