fastjson生成JSON字符串的时候出现$ref

本文介绍如何使用FastJSON处理对象间的循环引用问题,并提供禁用循环引用检测的方法。通过$ref标记,FastJSON能有效避免序列化过程中的堆栈溢出错误。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

转载自:http://wuzhuti.cn/201426!826!05!130202.html


      可以通过选项 DisableCircularReferenceDetect来禁止循环引用检测:

      

JSON.toJSONString( yourObject, SerializerFeature.DisableCircularReferenceDetect);

     循环引用 很多场景中,我们需要序列化的对象中存在循环引用,在许多的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)

### 将JSON字符串解析为泛型实体类的方法 在编程中,将JSON字符串解析为泛型实体类是一个常见的需求。以下是实现这一目标的具体方式。 #### 1. 使用 `json_serializable` 库(适用于 Flutter/Dart) 如果是在 Dart 或者 Flutter 中开发应用,则可以通过 `json_serializable` 插件来处理泛型的支持。从 v3.5.0 开始,该插件允许通过设置 `genericArgumentFactories` 参数为 `true` 来启用泛型支持[^1]。随后需要调整 `fromJson` 和 `toJson` 的方法逻辑以适配泛型结构。例如: ```dart @JsonSerializable(genericArgumentFactories: true) class GenericEntity<T> { final T data; GenericEntity(this.data); factory GenericEntity.fromJson(Map<String, dynamic> json, T Function(Object? json) fromJsonT) => _$GenericEntityFromJson(json, fromJsonT); } ``` 这种方法的优势在于能够自动生成序列化/反序列化的代码,减少手动编写的工作量。 --- #### 2. Java 中使用反射机制与第三方库 对于 Java 而言,可以借助阿里巴巴的 FastJSON 库或者 Jackson/Gson 等工具来进行 JSON 字符串到泛型对象的转换。下面分别介绍两种常见的方式。 ##### (1)FastJSON 实现 FastJSON 提供了强大的类型推断能力,尤其适合复杂的嵌套数据结构。以下是一个基于抽象类的设计模式示例[^4]: ```java import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; public abstract class AbstractParser<T> { public T parse(String jsonString) { return JSON.parseObject(jsonString, new TypeReference<T>() {}); } } // 示例调用 public static void main(String[] args) { String jsonData = "[{'name':'Alice','age':25}, {'name':'Bob','age':30}]"; AbstractParser<List<Person>> parser = new AbstractParser<>(); List<Person> persons = parser.parse(jsonData); System.out.println(persons); } ``` 这里的关键点是利用 `TypeReference` 明确指定泛型的实际类型参数,从而避免因类型擦除而导致的信息丢失。 ##### (2)Jackson 实现 Jackson 是另一个流行的 JSON 处理框架,在处理复杂的数据模型方面表现优异。其核心思想同样是通过显式的类型定义解决泛型问题: ```java import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.ObjectMapper; import java.io.IOException; import java.util.List; public class JsonToGenericExample { private static final ObjectMapper objectMapper = new ObjectMapper(); public static <T> T convertToObject(String jsonString, Class<T> clazz) throws IOException { return objectMapper.readValue(jsonString, clazz); } public static <T> T convertToList(String jsonString, TypeReference<?> typeRef) throws IOException { return objectMapper.readValue(jsonString, typeRef); } public static void main(String[] args) throws Exception { String jsonArrayStr = "[{\"id\":1,\"name\":\"Item A\"},{\"id\":2,\"name\":\"Item B\"}]"; // 泛型列表解析 List<Item> items = convertToList(jsonArrayStr, new TypeReference<>() {}); System.out.println(items); } } ``` 上述代码片段展示了如何通过 `TypeReference` 定义具体的泛型类型并将其传递给 Jackson 进行解析操作[^5]。 --- #### 3. 基于原生 API 手动解析 如果不希望引入额外的依赖项,也可以采用标准库中的 `JSONObject` 和 `JSONArray` 类自行完成解析过程。不过这种方式通常较为繁琐且容易出错,尤其是在面对深层次嵌套的对象时[^3]。例如: ```java import org.json.JSONArray; import org.json.JSONObject; import java.util.ArrayList; import java.util.List; public class ManualParsingExample { public static List<Item> parseItems(String jsonString) { JSONArray array = new JSONArray(jsonString); List<Item> result = new ArrayList<>(); for (int i = 0; i < array.length(); ++i) { JSONObject obj = array.getJSONObject(i); Item item = new Item(); item.setId(obj.getInt("id")); item.setName(obj.getString("name")); result.add(item); } return result; } public static void main(String[] args) { String input = "[{\"id\":1,\"name\":\"Apple\"},{\"id\":2,\"name\":\"Banana\"}]"; List<Item> parsedResult = parseItems(input); System.out.println(parsedResult); } } ``` 尽管如此,推荐优先考虑成熟的开源解决方案以提升效率和可靠性。 --- ### 总结 无论是前端还是后端环境,都有多种途径可供选择用于将 JSON 数据映射至相应的泛型实体类。具体选用哪种方案取决于项目的技术栈以及个人偏好等因素。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值