fastjson把对象转化成json避免$ref

本文介绍FastJSON如何处理对象间的循环引用问题,并提供禁用循环引用检测的方法。通过使用DisableCircularReferenceDetect特性,可以避免序列化过程中出现堆栈溢出错误。

转:http://blog.csdn.net/mephistodemon1/article/details/19118493

DisableCircularReferenceDetect来禁止循环引用检测:

JSON.toJSONString(..., SerializerFeature.DisableCircularReferenceDetect)

当进行toJSONString的时候,默认如果重用对象的话,会使用引用的方式进行引用对象。

"颜色": [
      {
        "$ref": "$.itemSkuList[0].itemSpecificationList[0]"
      }, 
      {
        "$ref": "$.itemSkuList[1].itemSpecificationList[0]"
      }
    ]

循环引用

很多场景中,我们需要序列化的对象中存在循环引用,在许多的json库中,这会导致stackoverflow。在功能强大的fastjson中,你不需要担心这个问题。例如:

A a = new A();
B b = new B(a);
a.setB(b);
String text = JSON.toJSONString(a); //{"b":{"a":{"$ref":".."}}}
A a1 = JSON.parseObject(text, A.class);
Assert.assertTrue(a1 == a1.getB().getA());

引用是通过"$ref"来表示的

引用 描述
"$ref":".." 上一级
"$ref":"@" 当前对象,也就是自引用
"$ref":"$" 根对象
"$ref":"$.children.0" 基于路径的引用,相当于 root.getChildren().get(0)

在将包含元素的 `List` 集合转换为 JSON 格式时出现 `$ref` 的问题,通常是由于 Fastjson 检测到对象之间的重复引用或循环引用所导致的。Fastjson 默认开启了循环引用检测机制,当序列化过程中发现对象之间存在嵌套引用关系时,会通过 `$ref` 来标记引用路径,以避免无限递归和栈溢出异常(`StackOverflowError`)[^3]。 ### 出现 `$ref` 的原因 1. **重复引用**:某个对象在集合中被多次引用,Fastjson 为了节省空间和避免重复序列化,会使用 `$ref` 来标记该对象的首次出现位置。 2. **循环引用**:对象之间存在互相引用关系,例如 A 引用 B,B 又引用 A,Fastjson 检测到这种情况后会通过 `$ref` 来避免无限递归。 3. **嵌套结构复杂**:当 `List` 中包含多层嵌套的对象结构时,Fastjson 会尝试通过路径表达式(如 `$.list[0]`)来标识对象的引用位置[^2]。 ### 解决方法 #### 方法一:关闭循环引用检测 可以通过关闭 Fastjson 的循环引用检测功能来避免 `$ref` 的出现。在序列化配置中设置 `DisableCircularReferenceDetect` 参数: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.serializer.SerializerFeature; public class JsonUtil { public static String toJson(Object object) { return JSON.toJSONString(object, SerializerFeature.DisableCircularReferenceDetect); } } ``` 这种方式适用于对象结构中存在合理循环引用的情况,但需要注意关闭检测后可能导致输出的 JSON 数据量增大,甚至在极端情况下引发内存问题[^1]。 #### 方法二:配置 Spring Boot 中的 Fastjson 转换器 如果是在 Spring Boot 项目中使用 Fastjson 进行 HTTP 消息转换,可以在配置类中设置 `FastJsonConfig` 来禁用循环引用检测: ```java import com.alibaba.fastjson.serializer.SerializerFeature; import com.alibaba.fastjson.support.config.FastJsonConfig; import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; import java.util.Collections; @Configuration public class FastJsonConfigSetup { @Bean public HttpMessageConverters fastJsonHttpMessageConverters() { FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter(); FastJsonConfig fastJsonConfig = new FastJsonConfig(); fastJsonConfig.setSerializerFeatures( SerializerFeature.PrettyFormat, SerializerFeature.DisableCircularReferenceDetect ); fastConverter.setFastJsonConfig(fastJsonConfig); return new HttpMessageConverters(Collections.singletonList(fastConverter)); } } ``` 此配置方式适用于全局控制 Fastjson 在 Spring Boot 中的序列化行为,确保返回的 JSON 不包含 `$ref` 引用标记[^4]。 #### 方法三:深拷贝对象 如果对象结构中存在重复引用,但不需要保留引用关系,可以考虑在序列化前对对象进行深拷贝,以消除引用关系。这种方式较为复杂,适用于需要严格控制输出格式的场景。 --- ###
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值