后台传递json数据到前台时报There is a cycle in the hierarchy!

本文讨论了在使用JSON序列化时遇到的实体类属性互相引用导致的死循环问题,并提供了通过配置排除指定属性的方法来解决此问题的解决方案。

 

 

 

实体Menu有两个属性

       private Set roleMenus = new HashSet(0);

 

private Set newsMenus = new HashSet(0);

 

因此在查询出List<Menu> menuList,并转换成json数据时,

这两个属性互相引用造成了死循环,于是报错:There is a cycle in the hierarchy!

 

解决办法:

JsonConfig config = new JsonConfig();
config.setExcludes(new String[]{"roleMenus","newsMenus"();

String str = JSONArray.fromObject(menuList,config).toString();

 

 

 

 

 

 

 

 

 

 

### 避免 JSON 序列化时的循环引用问题 在将 Java 对象序列化为 JSON 字符串时,如果对象之间存在循环引用(例如对象 A 引用了对象 B,而对象 B 又引用了对象 A),则会抛出 `net.sf.json.JSONException: There is a cycle in the hierarchy` 异常。这种问题通常出现在具有双向关联关系的实体类中,尤其是在处理数据库实体与 JSON 数据转换时非常常见。 为了避免这种异常,可以采取以下几种解决方案: #### 1. 使用 `JsonConfig` 排除特定字段 通过 `JsonConfig` 配置对象,可以设置需要排除的字段,从而避免循环引用的发生。例如,在部门与员工的关系中,可以通过排除员工集合字段或部门字段来打破循环链路: ```java public String getAllDep() { List list = deptDAO.findAll(); JsonConfig config = new JsonConfig(); config.setExcludes(new String[]{"emps"}); // 排除员工集合字段 String json = JSONArray.fromObject(list, config).toString(); return json; } public String getAllEmp(int id) { List list = empDAO.findByProperty("dept.deptId", id); JsonConfig config = new JsonConfig(); config.setExcludes(new String[]{"dept"}); // 排除部门字段 String json = JSONArray.fromObject(list, config).toString(); return json; } ``` 该方法简单直接,适用于字段明确且可以安全排除的场景[^5]。 #### 2. 使用 `CycleDetectionStrategy` 配置循环检测策略 `net.sf.json` 提供了 `CycleDetectionStrategy` 来处理循环引用。可以通过设置 `CycleDetectionStrategy.LENIENT` 来允许序列化过程中忽略循环引用: ```java JsonConfig jsonConfig = new JsonConfig(); jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); JSONObject jsonObject = JSONObject.fromObject(object, jsonConfig); ``` 这种方式不会抛出异常,而是将循环引用的字段设置为 `null`,适用于需要保留大部分字段但无法避免循环引用的情况[^4]。 #### 3. 使用自定义 `JsonValueProcessor` 对于特定类型的字段,可以通过实现 `JsonValueProcessor` 接口来控制其序列化行为。例如,可以定义一个处理器,将循环引用字段转换为 ID 而不是整个对象: ```java public class DepartmentValueProcessor implements JsonValueProcessor { public Object processArrayValue(Object value, JsonConfig jsonConfig) { return null; } public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) { if (value instanceof Department) { return ((Department) value).getId(); } return null; } } ``` 然后在配置中注册该处理器: ```java JsonConfig config = new JsonConfig(); config.registerJsonValueProcessor(Department.class, new DepartmentValueProcessor()); ``` 这种方式可以更精细地控制 JSON 输出,适用于需要保留部分关联信息但又不希望出现循环引用的场景[^2]。 #### 4. 使用其他 JSON 库替代 `net.sf.json` 如果项目允许更换 JSON 序列化库,可以考虑使用如 Jackson 或 Gson 等更现代的库,它们对循环引用的支持更加灵活。例如,使用 Jackson 可以通过 `@JsonManagedReference` 和 `@JsonBackReference` 注解来处理双向关联: ```java public class Department { @JsonManagedReference private List<Employee> employees; } public class Employee { @JsonBackReference private Department department; } ``` 这些注解可以有效地避免序列化时的循环引用问题,同时保持对象结构的完整性。 ### 总结 处理 `net.sf.json.JSONException: There is a cycle in the hierarchy` 异常的关键在于识别并打破对象之间的循环引用关系。可以通过字段排除、自定义处理器、配置循环检测策略或更换 JSON 库等方式实现这一目标。选择合适的方案取决于具体的应用场景和系统架构。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值