使用JSONObject转换字符串时碰上相互关联,报错无限循环的错误。There is a cycle in the hierarchy
有关这个问题,其实网上已经有不少介绍,大多是复制粘贴的三种方案:
一.
- JsonConfig jsonConfig = new JsonConfig();
- jsonConfig.setExcludes(new String[]{"filterAttibute"})
- 使用JsonConfig设置过滤属性
二.
- jsonConfig.setJsonPropertyFilter(new PropertyFilter() {
- @Override
- public boolean apply(Object source, String name, Object value) {
- if(name.equals("filterAttibute")){
- return true;
- }
- return false;
- }
- });
使用JsonValueProcessor ,自己定义一个json解析方案
- jsonConfig.registerJsonValueProcessor(YourClass.class,
- new MyJsonValueProcessor(new String[]{"filterAttibute"},YourClass.class));
-
- jsonConfig.registerJsonValueProcessor(YourClass.class, new JsonValueProcessor() {
@Override
public Object processObjectValue(String key, Object value,
JsonConfig jsonConfig) {
// TODO Auto-generated method stub
return null;
}
@Override
public Object processArrayValue(Object value, JsonConfig jsonConfig) {
// TODO Auto-generated method stub
return null;
}
});
这三种方案我都试过,都是可行的,大家也可以从网上能搜到,我就不列举了。下面说一下我碰上的问题。
使用第一种方案,过滤掉 我认为会出现循环的字段时,There is a cycle in the hierarchy仍然存在。不是方法不好用,而是忽略了转换原理,而遗漏了一种情况。
在把对象内所有属性转换为json字符串,其实是lib通过反射获取所有get方法,得到属性值的,如果把field的get方法去掉,可以明显的发现,这个field并没有打印出来,比较晚就不贴代码了,大家可以自己试验下。
所以,刚才提到的忽略的情况,是 get*这样的方法。如果这个方法返回的值是嵌套对象的话,问题仍然存在。
public ClassA getPertUser(){
return this.classA;
}
return this.classA;
}
所以,在忽略字段类型中也要写出来。注意遵循反射取值方法,讲首字母小写。
如:String[] filterStrs = new String[]{"creator","pertUser"}; //过滤get方法值
还有一种我认为比较好的方法是,让需要特别对待bean,继承JSONString接口,通过重写toJSONString() ,来定制自己需要的输出。
毕竟json是用来数据传输的,而一个对象中可能有多个不用传递的属性值,自己定制能更加清晰些。自己定制还有一个好处,就是特殊类型可以用自己需要的方式展示出来,Date就是一个典型。因此 JsonValueProcessor 和 自定义toJsonString的方法我认为更加好用一下
以上是我在处理There is a cycle in the hierarchy时的解决方案,如果有更好的办法,请大家告诉我。欢迎批评指点,谢谢。
附:Json-lib包需要依赖多个包,在
http://json-lib.sourceforge.net/ 上有详细的介绍,
jakarta commons-lang 2.5现在自己下载可能下不到,下3.*的版本也会报错,注意可以下载2.6版本,能保证运行,我使用的是json-lib-2.1。
附:额,文章似乎不能放文件,之后我会把源码及json-lib依赖包放到我的资源中,并提供大家下载
json-lib包及所有依赖下载地址:
http://download.csdn.net/detail/jjsologuy/6845509