自己编写的一个Json工具类,实现了反射将整个Object转换为Json对象的功能,支持Hibernate的延迟加载对象

由于Json自己的String转换有问题,无法正确的转换中文为uxxxx的字符,因此改用DWR包内的JavascriptUtil处理 String类型。可以直接引用,还可以拆离出来,因为仅是一个转换工具类,跟DWR的没有依赖关系。这样就可以采用ISO-8859-1编码来传递所有 UNICODE了。

 代码:  

package com.aherp.framework.util;

import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONString;

/**
 * JSON工具类,反射的方式转换整个对象
 * 
@author Jim Wu
 *
 
*/

public class JSONUtil {

    
private static JSONUtil instance = null;
    
    
public JSONUtil(){}
    
    
/**
     * 代理类时做的检查.返回应该检查的对象.
     * 
@param bean
     * 
@return
     
*/

    
protected Object proxyCheck(Object bean){
        
return bean;
    }


    
static public String toJSONString(Object obj) throws JSONException{
        
return toJSONString(obj, false);
    }

    
    
static public String toJSONString(Object obj, boolean useClassConvert) throws JSONException{
        
if(instance == null)
            instance 
= new JSONUtil();
        
return instance.getJSONObject(obj, useClassConvert).toString();
    }


    
private String getJSONArray(Object arrayObj, boolean useClassConvert) throws JSONException{
        
        
if(arrayObj == null)
            
return "null";
        
        arrayObj 
= proxyCheck(arrayObj);
        
        JSONArray jSONArray 
= new JSONArray();
        
if(arrayObj instanceof Collection){
            Iterator iterator 
= ((Collection)arrayObj).iterator();
            
while(iterator.hasNext()){
                Object rowObj 
= iterator.next();
                
if(rowObj == null)
                    jSONArray.put(
new JSONStringObject(null));
                
else if(rowObj.getClass().isArray() || rowObj instanceof Collection)
                    jSONArray.put(getJSONArray(rowObj, useClassConvert));
                
else
                    jSONArray.put(getJSONObject(rowObj, useClassConvert));
            }

        }

        
if(arrayObj.getClass().isArray()){
            
int arrayLength = Array.getLength(arrayObj);
            
for(int i = 0; i < arrayLength; i ++){
                Object rowObj 
= Array.get(arrayObj, i);
                
if(rowObj == null)
                    jSONArray.put(
new JSONStringObject(null));
                
else if(rowObj.getClass().isArray() || rowObj instanceof Collection)
                    jSONArray.put(getJSONArray(rowObj, useClassConvert));
                
else
                    jSONArray.put(getJSONObject(rowObj, useClassConvert));
            }

        }

        
return jSONArray.toString();
    }


    JSONStringObject getJSONObject(Object value, 
boolean useClassConvert) throws JSONException{

        
//处理原始类型
        if (value == null{
            
return new JSONStringObject("null");
        }

        value 
= proxyCheck(value);
        
if (value instanceof JSONString) {
            Object o;
            
try {
                o 
= ((JSONString)value).toJSONString();
            }
 catch (Exception e) {
                
throw new JSONException(e);
            }

            
throw new JSONException("Bad value from toJSONString: " + o);
        }

        
if (value instanceof Number) {
            
return new JSONStringObject(JSONObject.numberToString((Number) value));
        }

        
if (value instanceof Boolean || value instanceof JSONObject ||
                value 
instanceof JSONArray) {
            
return new JSONStringObject(value.toString());
        }

        
if (value instanceof String)
            
return new JSONStringObject('"' + JavascriptUtil.escapeJavaScript(value.toString()) + '"');
        
if (value instanceof Map) {
            
            JSONObject jSONObject 
= new JSONObject();

            Iterator iterator 
= ((Map)value).keySet().iterator();
            
while(iterator.hasNext()){
                String key 
= iterator.next().toString();
                Object valueObj 
= ((Map)value).get(key);
                jSONObject.put(key, getJSONObject(valueObj, useClassConvert));
            }

            
return new JSONStringObject(jSONObject.toString());
        }


        
//class
        if(value instanceof Class)
            
return new JSONStringObject(JavascriptUtil.escapeJavaScript(((Class)value).getSimpleName()));
        
        
//数组
        if (value instanceof Collection || value.getClass().isArray()) {
            
return new JSONStringObject(getJSONArray(proxyCheck(value), useClassConvert));
        }


        
return reflectObject(value, useClassConvert);
    }
//value.equals(null)

    
private JSONStringObject reflectObject(Object bean, boolean useClassConvert){
        JSONObject jSONObject 
= new JSONObject();

        Class klass 
= bean.getClass();
        Method[] methods 
= klass.getMethods();
        
for (int i = 0; i < methods.length; i += 1{
            
try {
                Method method 
= methods[i];
                String name 
= method.getName();
                String key 
= "";
                
if (name.startsWith("get")) {
                    key 
= name.substring(3);
                }
 else if (name.startsWith("is")) {
                    key 
= name.substring(2);
                }

                
if (key.length() > 0 &&
                        Character.isUpperCase(key.charAt(
0)) &&
                        method.getParameterTypes().length 
== 0{
                    
if (key.length() == 1{
                        key 
= key.toLowerCase();
                    }
 else if (!Character.isUpperCase(key.charAt(1))) {
                        key 
= key.substring(01).toLowerCase() +
                            key.substring(
1);
                    }

                    Object elementObj 
= method.invoke(bean, null);
                    
if(!useClassConvert && elementObj instanceof Class)
                        
continue;

                    jSONObject.put(key, getJSONObject(elementObj, useClassConvert));
                }

            }
 catch (Exception e) {
                
/* forget about it */
            }

        }

        
return new JSONStringObject(jSONObject.toString());
    }

}

 

package com.aherp.framework.util;

import org.json.JSONString;

public class JSONStringObject implements JSONString {

    
private String jsonString = null;
    
    
public JSONStringObject(String jsonString){
        
this.jsonString = jsonString;
    }


    @Override
    
public String toString() {
        
return jsonString;
    }


    
public String toJSONString() {
        
return jsonString;
    }

}

 

调用测试程序

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;


public class AObj {
    
private int ii = 7;
    
private boolean bb = true;
    
private String ss = "你好";
    
private List aList = new ArrayList();

    
public AObj(){
        aList.add(
"hello");
        aList.add(
false);
        aList.add(
new BObj());
        aList.add(
new HashMap());
    }

    
    
public boolean isBb() {
        
return bb;
    }

    
public void setBb(boolean bb) {
        
this.bb = bb;
    }

    
public int getIi() {
        
return ii;
    }

    
public void setIi(int ii) {
        
this.ii = ii;
    }

    
public String getSs() {
        
return ss;
    }

    
public void setSs(String ss) {
        
this.ss = ss;
    }

    
public List getAList() {
        
return aList;
    }

    
public void setAList(List list) {
        aList 
= list;
    }

}


import java.math.BigDecimal;
import java.util.HashMap;


public class BObj {

    
private HashMap innerhm = new HashMap();
    
    
public BObj(){
        
double dd = 7.4354;
        innerhm.put(
"gigi""高兴");
        innerhm.put(
"sina"new BigDecimal(dd));
    }


    
public HashMap getInnerhm() {
        
return innerhm;
    }


    
public void setInnerhm(HashMap innerhm) {
        
this.innerhm = innerhm;
    }

}



public class CObj extends AObj{

    
private Object[] oarray = new Object[]{352false"kick"};

    
public Object[] getOarray() {
        
return oarray;
    }


    
public void setOarray(Object[] oarray) {
        
this.oarray = oarray;
    }

}


import org.json.JSONException;

import com.aherp.framework.util.JSONUtil;

public class Test {   
    
public static void main(String[] args) throws JSONException {
        CObj cObj 
= new CObj();
        System.out.println(JSONUtil.toJSONString(cObj));
    }
   
}
   



输出:
{"AList":["hello",false,{"innerhm":{"gigi":"/u9AD8/u5174","sina":7.4353999999999995651478457148186862468719482421875}},{}],"ii":7,"oarray":[352,false,"kick"],"ss":"/u4F60/u597D","bb":true}

如 果需要支持Hibernate,那么必须弄清其机制。Hibernate采用CGLIB对VO对象进行字节码增加,实际机制就是使用一个原类型的 proxy子类,其子类实现了HibernateProxy接口。其接口有一个isUninitialized的判断方法,用来判断该代理类是否已经初始 化(还记得在事务外使用延迟加载的对象会抛no Session的错误吗,正是由于实际使用的对象已经变成原来类的子类proxy了)。而对于one-to-many映射时,很难判断对象只加载一次,因 此为了避免递归调用死循环,忽略了Hibernate的one-to-many集合的递归反射。其原理和many-to-one一样,也是一个子类化的 proxy,具有PersistentSet的接口。

因此,支持Hibernate的JSONUtil如下:
package com.aherp.framework.util;

import org.hibernate.collection.PersistentSet;
import org.hibernate.proxy.HibernateProxy;
import org.hibernate.proxy.LazyInitializer;
import org.json.JSONException;

/**
 * 支持Hibernate的JSONUtil.
 * 自动检测是否已经代理加载,如果未加载,则将对象仅加载为OID
 * @author Jim Wu
 *
 
*/

public class HiJSONUtil extends JSONUtil 
{

    private static HiJSONUtil instance 
= null;

    static public String toJSONString(Object obj) throws JSONException
{
        
return toJSONString(obj, false);
    }

    
    static public String toJSONString(Object obj, 
boolean useClassConvert) throws JSONException{
        
if(instance == null)
            instance 
= new HiJSONUtil();
        
return instance.getJSONObject(obj, useClassConvert).toString();
    }


    @Override
    protected Object proxyCheck(Object bean) 
{
        System.out.println(
"Class is ..." + bean.getClass().getName());
        
if(bean instanceof HibernateProxy){
            LazyInitializer lazyInitializer 
= ((HibernateProxy)bean).getHibernateLazyInitializer();
            
if(lazyInitializer.isUninitialized()){
                System.out.println(
">>>>>lazyInitializer.getIdentifier()="+ lazyInitializer.getIdentifier());
                
return lazyInitializer.getIdentifier();
            }

        }

        
if(bean instanceof PersistentSet){
            
return new String[]{}//忽略hibernate one-to-many
        }

        
return bean;
    }

}

;

但是这样还是有个问题,当one-to-one具备双向映射关系时,会陷入调用递归死循环。因此避免这样的情况
posted @ 2008-05-23 09:10  dainiao01  阅读(977)  评论(0编辑  收藏  举报