相信大家做过JSON相关的东西对这个异常并不陌生,这个异常是由于JSONObject插件内部会无限拆解你传入的对象,直到没有可拆解为止,问题就在这,如果你传入的对象有外键关系,或者相互引用,那么内部就会死循环,也就会抛出这个异常
解决办法,一种网上通用的:过滤
这种方法是有弊端的,比如我的一条评论记录,包括有用户id作为记录的外键,假如过滤掉了,那么你需要在页面显示谁写的这条记录显然需要用户信息,写VO类吗?个人认为并不是什么明智之举。
下面给出一种解决思路:
首先是借用JSONObject里的JsonValueProcessor接口,我们自己实现该接口,代码如下:
package com.publics;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
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;
}
public Object processArrayValue(Object arg0, JsonConfig arg1) {
// TODO Auto-generated method stub
return null;
}
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, clazz);
method = pd.getReadMethod();
String v = String.valueOf(method.invoke(value));
json.append("'"+properties+"':'"+v+"'");
json.append(i != properties.length-1?",":"");
}
json.append("}");
}catch (Exception e) {
e.printStackTrace();
}
return JSONObject.fromObject(json.toString());
}
}
在processObjectValue这个方法里重写,具体请看代码,另外在构造方法里我给出了两个参数,一个是需要留下来的属性名,通过数组传递,另一个是一个Class<?> type,也是相关上面说到例子中的属性类,是用来在后面通过该属性类调用java反射机制获取属性值,在取到相关属值后组装成字符串,最后通过JSONObject.fromObject来输出,不这样输出会有问题,至于什么问题,有好奇心的同学自己试试下面是调用方法:
JsonConfig config = new JsonConfig();
config.setIgnoreDefaultExcludes(false); //设置 不能忽略默认的excludes
config.registerJsonValueProcessor(Users.class, new ObjectJsonValueProcessor(new String[]{"id","username","email"},Users.class));
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
解决办法,一种网上通用的:过滤
- jsonConfig.setExcludes(new String[]{"dianYuanHeSuans"})
这种方法是有弊端的,比如我的一条评论记录,包括有用户id作为记录的外键,假如过滤掉了,那么你需要在页面显示谁写的这条记录显然需要用户信息,写VO类吗?个人认为并不是什么明智之举。
下面给出一种解决思路:
首先是借用JSONObject里的JsonValueProcessor接口,我们自己实现该接口,代码如下:
package com.publics;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import net.sf.json.JSONObject;
import net.sf.json.JsonConfig;
import net.sf.json.processors.JsonValueProcessor;
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;
}
public Object processArrayValue(Object arg0, JsonConfig arg1) {
// TODO Auto-generated method stub
return null;
}
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, clazz);
method = pd.getReadMethod();
String v = String.valueOf(method.invoke(value));
json.append("'"+properties+"':'"+v+"'");
json.append(i != properties.length-1?",":"");
}
json.append("}");
}catch (Exception e) {
e.printStackTrace();
}
return JSONObject.fromObject(json.toString());
}
}
在processObjectValue这个方法里重写,具体请看代码,另外在构造方法里我给出了两个参数,一个是需要留下来的属性名,通过数组传递,另一个是一个Class<?> type,也是相关上面说到例子中的属性类,是用来在后面通过该属性类调用java反射机制获取属性值,在取到相关属值后组装成字符串,最后通过JSONObject.fromObject来输出,不这样输出会有问题,至于什么问题,有好奇心的同学自己试试下面是调用方法:
JsonConfig config = new JsonConfig();
config.setIgnoreDefaultExcludes(false); //设置 不能忽略默认的excludes
config.registerJsonValueProcessor(Users.class, new ObjectJsonValueProcessor(new String[]{"id","username","email"},Users.class));
config.setCycleDetectionStrategy(CycleDetectionStrategy.LENIENT);
JSONArray jsonArray =JSONArray.fromObject(ArrayList对象,config);
这时如果出现Session关闭的情况时,请用Hibernate.initialize(comments.getXxx());初始化一下