問題:
net.sf.json.JSONException: There is a cycle in the hierarchy!
at net.sf.json.util.CycleDetectionStrategy$StrictCycleDetectionStrategy.handleRepeatedReferenceAsObject(CycleDetectionStrategy.java:97)
***************************************************************************************************************************************************
在查問一些資料後,總結出解決該問題的兩種辦法,現在與大家分享一下。
其一:根據原理來解決,如果需要解析的數據間存在級聯關係,而互相嵌套引用,在hibernate中極容易嵌套而拋出net.sf.json.JSONException: There is a cycle in the hierarchy異常。
舉個例子:現在有實驗(Lib)和類別(Libtype)兩張表,每個實驗都對應着一個類別,那麼,在類別的POJO中,就會如下代碼:
private Integer ltid; //類別ID
private String ltype; //類別名稱
private Set libs = new HashSet(0); //對應的實驗集
當我們寫如下代碼時,會報錯:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
LibtypeDAO libtypeDAO = new LibtypeDAO();
List<Libtype> list = libtypeDAO.findAll();
JSONArray jsonArray = JSONArray.fromObject(list);
return null;
}
原因很簡單,在Libtype中,有一個與List無關的屬性值,即libs,我們只需要ltid和ltype,所以報錯。
根據我在網上查找的資料,解決辦法有如下3種:
1.設置JSON-LIB讓其過濾掉引起循環的字段:
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
LibtypeDAO libtypeDAO = new LibtypeDAO();
List<Libtype> list = libtypeDAO.findAll();
JsonConfig jsonConfig = new JsonConfig(); //建立配置文件
jsonConfig.setIgnoreDefaultExcludes(false); //設置默認忽略
jsonConfig.setExcludes(new String[]{"libs"}); //此處是亮點,只要將所需忽略字段加到數組中即可,在上述案例中,所要忽略的是“libs”,那麼將其添到數組中即可,在實際測試中,我發現在所返回數組中,存在大量無用屬性,如“multipartRequestHandler”,“servletWrapper”,那麼也可以將這兩個加到忽略數組中.
JSONArray jsonArray = JSONArray.fromObject(list,jsonConfig); //加載配置文件
return null;
}
2.設置JSON-LIB的setCycleDetectionStrategy屬性讓其自己處理循環,省事但是數據過於複雜的話會引起數據溢出或者效率低下。
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
LibtypeDAO libtypeDAO = new LibtypeDAO();
List<Libtype> list = libtypeDAO.findAll();
JsonConfig jsonConfig = new JsonConfig(); //建立配置文件
jsonConfig.setIgnoreDefaultExcludes(false); //設置默認忽略
jsonConfig.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT); //此處是亮點,不過經過測試,第2種方法有些悲劇,雖然可以使用,但其結果貌似循環數次,至於爲啥,還請高人指點。
JSONArray jsonArray = JSONArray.fromObject(list,jsonConfig); //加載配置文件
return null;
}
3.最爲原始的辦法,自己寫個JavaBean,用forEach循環,添加到List中,這個方法我看網上有人成功,我沒試,但大概過程可以寫出來,其結果正確性有待檢驗。
JavaBean:
public LibtypeForm{
int ltid;
string ltname;
}
public ActionForward execute(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response){
LibtypeDAO libtypeDAO = new LibtypeDAO();
List<Libtype> list = libtypeDAO.findAll();
List<LibtypeForm> formList = new ArrayList();
for(Libtype libtype : list){
LibtypeForm form = new LibtypeForm();
form.setLtid(libtype .getLtid);
form.setLtname(libtype.getLtname);
formList.add(form);
}
JSONArray jsonArray = JSONArray.fromObject(formList);
return null;
}
如果有更好的方法,還請高人指點。
.