我使用JSON layout logging用于基于 Spring Boot (2.1.6) 的 Web 应用程序的 Log4J2。
我验证 Converter
s 中请求的传入参数.
如果参数无效,则会抛出 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/