相信大家做过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 yxkong
*/
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是你要处理的属性类型