問題:Struts2框架的rest-plugin插件中jsonlib庫,在序列化時因對象循環引用時觸發異常。為了在解決這個問題,修改該插件的源代碼并重發編譯。
思路:解決這個問題,用了一個簡單的思路,就是將jsonlib序列化前,先將循環引用解除,在代碼中使用遞歸和堆棧。
缺失:由于該方式采用如果存在循環引用就返回null值的方式,因此這種方式不具反序列化可行性,需要進一步改進思路。
參考:目前開源的fastjson已經解決了對象循環引用問題
// 處理數組的循環引用
private Object disCycleArray(Object obj, Object owner)
throws IllegalArgumentException, IllegalAccessException {
if (null != obj) {
if (!isRefObject(getComponetType(obj)))
return obj;
Object[] objects = (obj instanceof Collection) ? ((Collection) obj)
.toArray() : ((Object[]) obj);
for (int i = 0; i < objects.length; i++) {
objects[i] = disCycleObject(objects[i], owner);
}
if (obj instanceof Collection) {
Set collection = new HashSet();
CollectionUtils.addAll(collection, objects);
return collection;
}
return objects;
}
return null;
}
private Object disCycleObject(Object obj, Object owner)
throws IllegalArgumentException, IllegalAccessException {
if (null == obj)
return null;
else if (null == owner || obj == owner) {
roots.put(obj.hashCode(), obj);
} else {
if (!contains(roots, owner)) {
roots.put(owner.hashCode(), owner);
}
if (contains(roots, obj))
return null;
}
if (null != obj) {
Field[] fields = obj.getClass().getDeclaredFields();
for (Field f : fields) {
f.setAccessible(true);
Object value = f.get(obj);
if (null != value && !"".equals(value))
if (isArray(value)) {
Object newvalue = disCycleArray(value, obj);
f.set(obj, newvalue);
} else {
if (isRefObject(f.getType())) {
if (contains(roots, value)) {
f.set(obj, null);
} else {
Object newvalue = disCycleObject(value, obj);
f.set(obj, newvalue);
}
}
}
}
//roots.remove(obj.getClass().getName());
roots.remove(obj.hashCode());
return obj;
}
return null;
}
private Class getComponetType(Object obj) {
if (null != obj) {
if (isArray(obj)) {
Object[] objects = (obj instanceof Collection) ? ((Collection) obj)
.toArray() : ((Object[]) obj);
return objects.length > 0 ? (objects[0] == null ? null
: objects[0].getClass()) : null;
}
}
return null;
}
private boolean isRefObject(Class<?> clz) {
if (null != clz)
if (!clz.isPrimitive()
&& !clz.getName().startsWith("java.util")
&& !clz.getName().matches(
"java.lang.(?!\\bObject\\b$)\\S+$")
&& !clz.getName().startsWith("java.io")) {
return true;
}
return false;
}
private boolean contains(Map<Integer, Object> roots, Object obj) {
if (null != obj) {
Object target = roots.get(obj.hashCode());
if (null != target) {
return true;
}
}
return false;
}
private boolean isArray(Object obj) {
return obj instanceof Collection || obj.getClass().isArray();
}
posted on 2013-03-27 11:46
Coundy 閱讀(511)
評論(0) 編輯 收藏