文章目录
问题
今天遇到个问题,返回个自定义的对象,Jsckson在对其序列化时抛了堆栈溢出。
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: Infinite recursion (StackOverflowError); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: java.awt.Rectangle[“bounds2D”]->java.awt.Rectangle[“bounds2D”]->java.awt.Rectangle[“bounds2D”]->java.awt.Rectangle[“bounds2D”]->java.awt.Rectangle[“bounds2D”]->
…
…
一、分析
Controller调用结束后返回一个数据对象,for循环遍历conventers,找到支持application/json的HttpMessageConverter,然后将返回的数据序列化成json。spring-boot-starter-web默认是使用Jackson序列化返回数据,这个错误就是无限递归,所以根据异常信息首先找到问题所在的类:java.awt.Rectangle,以及属性:bounds2D,查看代码,确实存在递归关系。
public class Rectangle {
public Rectangle2D getBounds2D() {
return new Rectangle(x, y, width, height);
}
}
二、解决
1.@JsonIgnore
被标注的属性在序列化和反序列化时都会被忽略。
2.@JsonBackReference
序列化:@JsonBackReference的作用相当于@JsonIgnore
反序列化:如果没有@JsonManagedReference,则不会自动注入@JsonBackReference标注的属性(被忽略的父或子);如果有@JsonManagedReference,则会自动注入自动注入@JsonBackReference标注的属性。
总结
这个类是java.awt包下的,我们没办法直接在这个类上加以上两个注解,另外实际业务确实也没用到这个属性,也就是引起无线递归的属性:bounds2D。这时候还可以用新的方式解决:
Jackson替换为fastjson
排除Jackson依赖,增加fastjson依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.75</version>
</dependency>
增加fastjson配置
@Configuration
public class FastjsonConfiguration implements WebMvcConfigurer {
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
FastJsonHttpMessageConverter fastjsonConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat,
SerializerFeature.DisableCircularReferenceDetect);
fastjsonConverter.setFastJsonConfig(fastJsonConfig);
List<MediaType> fastjsonMediaTypes = new ArrayList<>();
fastjsonMediaTypes.add(MediaType.APPLICATION_JSON_UTF8);
fastjsonConverter.setSupportedMediaTypes(fastjsonMediaTypes);
converters.add(fastjsonConverter);
}
}