java - Spring ConversionFailedException 无法序列化为 JSON

标签 java spring spring-boot jackson log4j2

我使用JSON layout logging用于基于 Spring Boot (2.1.6) 的 Web 应用程序的 Log4J2。

我验证 Converters 中请求的传入参数.

如果参数无效,则会抛出 IllegalArgumentException。该异常被包装在 ConversionFailedException 中,而该异常又被包装在 MethodArgumentTypeMismatchException 中。

现在,当尝试使用 JSON 记录器记录此异常时,Jackson 序列化会陷入无限递归:

ERROR StatusLogger com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"]->java.util.LinkedHashMap["exception"]->org.springframework.web.method.annotation.MethodArgumentTypeMismatchException["cause"]->org.springframework.core.convert.ConversionFailedException["sourceType"]->org.springframework.core.convert.TypeDescriptor["resolvableType"]->org.springframework.core.ResolvableType["componentType"]->org.springframework.core.ResolvableType["componentType"])
 com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Direct self-reference leading to cycle (through reference chain: org.apache.logging.log4j.core.impl.Log4jLogEvent["message"]->java.util.LinkedHashMap["exception"]->org.springframework.web.method.annotation.MethodArgumentTypeMismatchException["cause"]->org.springframework.core.convert.ConversionFailedException["sourceType"]->org.springframework.core.convert.TypeDescriptor["resolvableType"]->org.springframework.core.ResolvableType["componentType"]->org.springframework.core.ResolvableType["componentType"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:77)
    at com.fasterxml.jackson.databind.SerializerProvider.reportBadDefinition(SerializerProvider.java:1191)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter._handleSelfReference(BeanPropertyWriter.java:944)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:721)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
    at com.fasterxml.jackson.databind.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:727)
    at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase.serializeFields(BeanSerializerBase.java:719)
    at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:155)
...

该错误似乎可以归结为 ConversionFailedException 内的 TypeDescriptor 无法序列化为 JSON。

重现:

val illegalArgumentException = java.lang.IllegalArgumentException("your value is bad")
val conversionFailedException = org.springframework.core.convert.ConversionFailedException(TypeDescriptor.valueOf(String.javaClass), TypeDescriptor.valueOf(String.javaClass), "some bad value", illegalArgumentException)
val mapper = com.fasterxml.jackson.databind.ObjectMapper()

mapper.writeValueAsString(conversionFailedException)

或者,如果您想将问题隔离到最小的单元:

com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(org.springframework.core.convert.TypeDescriptor.valueOf(String.javaClass))

规避这个问题的最佳方法是什么?

最佳答案

您收到的错误是因为org.springframework.core.ResolvableType有一个对其自身的引用:componentType,它创建了无限循环。

避免这种情况的一种方法是从 JSON 序列化/反序列化中全局排除 org.springframework.core.ResolvableType。您可以使用 Jackson 的 mixin 来做到这一点:

@JsonIgnoreType
public class MyMixInForIgnoreType {}

现在,在配置类中创建一个自定义对象映射器:

 @Bean
 @Primary 
 public ObjectMapper objectMapper () {
    ObjectMapper mapper = new Log4jJsonObjectMapper();
    mapper.addMixIn(org.springframework.core.ResolvableType.class, MyMixInForIgnoreType.class);
    return mapper;
}

关于java - Spring ConversionFailedException 无法序列化为 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57004379/

相关文章:

c# - 为什么不用 GOTO 语句?

java - 在 Netbeans 向导中使用 JFrame 而不是 JDialog

java - 计算连续的奇数变化

java - 将证书导入 Spring 的问题

java - 是否可以使用 Spring Batch 处理从 Web 应用程序上传的多部分 CSV 文件?

java - 将对象从已实现的类添加到数组

java - 当上下文关闭时,已经创建的 bean 会发生什么

java - 如何通过注释有条件地使用自定义 JsonSerializer

java - 如何验证@RequestParams 不为空?

spring-boot - Axon 框架重试逻辑