信大家做過JSON相關的東西對這個異常並不陌生,這個異常是由於JSONObject插件內部會無限拆解你傳入的對象,直到沒有可拆解爲止,問題就在這,如果你傳入的對象有外鍵關係,或者相互引用,那麼內部就會死循環,也就會拋出這個異常
解決辦法,我們先說一種網上通用的:過濾
不錯,過濾肯定會解決該問題,過濾也有兩種方法:
一種是通過
jsonConfig.setExcludes(new String[]{"dianYuanHeSuans"})
該方法接受一個數組,也就是你需要過濾的字段,很簡單就能完成。
二種是通過
jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
@Override
public boolean apply(Object source, String name, Object value) {
if(name.equals("qualityChecks")){
return true;
}
return false;
}
});
這種方式,其實和第一種差不多,達到同樣的效果,也很簡單。
接下來是我主要想說的,其實這兩種方法,有種弊端
假如說我們一個User對象裏有個屬性是部門,引用的是Organzition這個對象,如果不做任何處理,調用JSONObject.fromObject方法同樣會拋出異常,如果我們通過過濾把Organzition屬性過濾了,那麼在前臺顯示的時候,將看不到有關部門的任何信息,其實需要顯示也不多,比如僅一個部門名字就可以,但是過濾掉什麼都沒有了,這個時候,很多同學會再建一個VO類來封裝前臺需要的屬性,這無疑增加了工作量和代碼的冗餘,LZ正是被該問困擾了很久,所以給出個解決辦法。
借用JSONObject裏的JsonValueProcessor接口,我們自己實現該接口,代碼如下:
/**
* 解決JSONObject.fromObject拋出"There is a cycle in the hierarchy"異常導致死循環的解決辦法
* @author LuoYu
* @date 2012-11-23
*/
public class ObjectJsonValueProcessor implements JsonValueProcessor {
/**
* 需要留下的字段數組
*/
private String[] properties;
/**
* 需要做處理的複雜屬性類型
*/
private Class<?> clazz;
/**
* 構造方法,參數必須
* @param properties
* @param clazz
*/
public ObjectJsonValueProcessor(String[] properties,Class<?> clazz){
this.properties = properties;
this.clazz =clazz;
}
@Override
public Object processArrayValue(Object value, JsonConfig jsonConfig) {
return "";
}
@Override
public Object processObjectValue(String key, Object value, JsonConfig jsonConfig) {
PropertyDescriptor pd = null;
Method method = null;
StringBuffer json = new StringBuffer("{");
try{
for(int i=0;i<properties.length;i++){
pd = new PropertyDescriptor(properties[i], clazz);
method = pd.getReadMethod();
String v = String.valueOf(method.invoke(value));
json.append("'"+properties[i]+"':'"+v+"'");
json.append(i != properties.length-1?",":"");
}
json.append("}");
}catch (Exception e) {
e.printStackTrace();
}
return JSONObject.fromObject(json.toString());
}
}
在processObjectValue這個方法裏重寫,具體請看代碼,另外在構造方法裏我給出了兩個參數,一個是需要留下來的屬性名,通過數組傳遞,另一個是一個Class<?> type,也是相關上面說到例子中的Organzition.class,是用來在後面通過該class調用java反射機制獲取屬性值,在取到相關屬值後組裝成字符串,最後通過JSONObject.fromObject來輸出,不這樣輸出會有問題,至於什麼問題,有好奇心的同學自己試試
下面是調用方法:
jsonConfig.registerJsonValueProcessor(Organzition.class,
new ObjectJsonValueProcessor(new String[]{"orgName","orgId"},Organzition.class));
其中,Organzition.class是你要處理的屬性類型