![解决easyUI中使用fastjson时出现$ref: “$.[0]“ 1 解决easyUI中使用fastjson时出现$ref: “$.[0]“ 1](/d/file/webqianduan/uphkcbl0wa3uphkcbl0wa3.png)
这里就是循环引用造成的。
一、问题分析:$ref:
- 接口返回的
api通过fastjson将实体转化为json字符串时,在传输的数据中如果出现相同的对象,fastjson默认开启引用检测会将相同的对象写成引用的形式; - 引用是通过
$ref来表示的 引用分两种; - 循环引用和重复引用。
| 占位符 | 类型 |
|---|---|
| “$ref”:”..” | 上一级 |
| “$ref”:”@” | 当前对象,也就是自引用 |
| “$ref”:”$” | 根对象 |
| “$ref”:”$.children.0″ | 基于路径的引用,相当于 root.getChildren().get(0) |
二、循环引用和重复引用
循环引用:即 A 对象引用 B 对象,B 对象又引用 A 对象,这种情况是要极力避免的,因为会导致堆栈溢出 (StackOverflowError);
三、$ref 问题的解决方案:
1. 局部关闭
将该对象在后端转换为 json 字符串返回给前端,使用 SerializerFeature.DisableCircularReferenceDetect关闭循环引用。
String str=JSON.toJSONString(object,SerializerFeature.DisableCircularReferenceDetect);
正常来说,我们的接口返回给前端的是 List 这种格式,如果采用这个方式,就要将返回值改为 String,不 优雅。当然也可以把这个字符串再次转换为对象,这样循环引用的问题就没有了。
2. spring boot 项目
public class FastJsonHttpMessageConverterEx extends
FastJsonHttpMessageConverter{
public FastJsonHttpMessageConverterEx(){
//在这里配置 fastjson 特性(全局设置的)
FastJsonConfig fastJsonConfig = new FastJsonConfig();
//fastJsonConfig.setDateFormat("yyyy-MM-dd HH:mm:ss"); //自定义时间格式
//fastJsonConfig.setSerializerFeatures(SerializerFeature.WriteMapNullValue);
//正常转换 null 值
fastJsonConfig.setSerializerFeatures(SerializerFeature.DisableCircularReference
Detect);
//关闭循环引用
this.setFastJsonConfig(fastJsonConfig);
}
@Override
protected boolean supports(Class<?> clazz) {
return super.supports(clazz);
}
}
@Configuration
public class WebMvcConfigurer extends WebMvcConfigurerAdapter {
.....
@Bean
public FastJsonHttpMessageConverterEx fastJsonHttpMessageConverterEx(){
return new FastJsonHttpMessageConverterEx();
}
}
3. 禁止序列化
如果循环引用的数据,前端用不到,那可以在实体类对应的字段加注解禁止序列化,这样前端就不会接 收到这个字段的引用数据了。
@JSONField(serialize = false) private List<Dept> dept
4. 普通 spring 项目
全局关闭循环引用检查:
<!-- 全局关闭循环引用检查,最好是不要关闭,不然有可能会 StackOverflowException --> <value>DisableCircularReferenceDetect</value>
在该字段的注解上指定序列化时关闭循环引用
//一个员工对应一个部门表 @JSONField(serialzeFeatures = SerializerFeature.DisableCircularReferenceDetect) private Dept dept=new Dept()
此种方法才是我们项目中的解决办法。