【问题标题】:Spring ConversionFailedException cannot be serialized to JSONSpring ConversionFailedException 无法序列化为 JSON
【发布时间】:2019-07-12 09:42:48
【问题描述】:

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

我验证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中的TypeDescriptors不能序列化为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))

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

【问题讨论】:

    标签: java spring spring-boot jackson log4j2


    【解决方案1】:

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

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

    @JsonIgnoreType
    public class MyMixInForIgnoreType {}
    

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

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

    【讨论】:

    • 谢谢,但您知道如何为Log4jJsonObjectMapper 设置此项吗?
    • 谢谢,但问题是 Log4jJsonObjectMapper 不使用 Spring 依赖注入来创建实例。看来我需要创建一个自定义的Layout 以确保我的日志不会中断:-(
    猜你喜欢
    • 2020-09-20
    • 1970-01-01
    • 1970-01-01
    • 2020-03-15
    • 1970-01-01
    • 2016-10-08
    • 2018-09-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多