zoukankan      html  css  js  c++  java
  • JSONObject转换分析

    net.sf.json.JSONObject采用反射的方式,对POJO进行转换。JSONObject类实现了JSON、Map和Comparable接口,如下:

    class JSONObject extends AbstractJSON implements JSON, Map, Comparable

    以Person类为例分析源码:

    public class Person {
        private String name;
        private int age;
        public String getName() {
            return name;
        }
        public void setName(String name) {
            this.name = name;
        }
        public int getAge() {
            return age;
        }
        public void setAge(int age) {
            this.age = age;
        }
    }

    fromObject(Object object)方法

    代码实现主要在JSONObject defaultBeanProcessing(Object bean, JsonConfig jsonConfig)方法中,如下:

     private static JSONObject defaultBeanProcessing(Object bean, JsonConfig jsonConfig) {
          Class beanClass = bean.getClass(); //获取类对象 class net.sf.json.mytest.Person
          PropertyNameProcessor propertyNameProcessor = jsonConfig.findJsonPropertyNameProcessor( beanClass );      
          Collection exclusions = jsonConfig.getMergedExcludes( beanClass );//需要排除的类信息,[metaClass, declaringClass, class]
          JSONObject jsonObject = new JSONObject();
          try{
             PropertyDescriptor[] pds = PropertyUtils.getPropertyDescriptors( bean );//获取POJO类的描述信息,包括属性、属性对应的读写操作,
    //[java.beans.PropertyDescriptor[name=age; propertyType=int; readMethod=public int net.sf.json.mytest.Person.getAge(); writeMethod=public void net.sf.json.mytest.Person.setAge(int)],
    //java.beans.PropertyDescriptor[name=class; propertyType=class java.lang.Class; readMethod=public final native java.lang.Class java.lang.Object.getClass()],
    //java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String net.sf.json.mytest.Person.getName(); writeMethod=public void net.sf.json.mytest.Person.setName(java.lang.String)]]
    PropertyFilter jsonPropertyFilter = jsonConfig.getJsonPropertyFilter(); //循环对所有属性进行处理 for( int i = 0; i < pds.length; i++ ){ boolean bypass = false; //获取属性名 String key = pds[i].getName(); if( exclusions.contains( key ) ){ continue; } if( jsonConfig.isIgnoreTransientFields() && isTransientField( key, beanClass ) ){ continue; } Class type = pds[i].getPropertyType(); try { pds[i].getReadMethod(); } catch( Exception e ) { // bug 2565295 String warning = "Property '" + key + "' of "+ beanClass+" has no read method. SKIPPED"; fireWarnEvent( warning, jsonConfig ); log.info( warning ); continue; } if( pds[i].getReadMethod() != null ){ Object value = PropertyUtils.getProperty( bean, key ); if( jsonPropertyFilter != null && jsonPropertyFilter.apply( bean, key, value ) ){ continue; } JsonValueProcessor jsonValueProcessor = jsonConfig.findJsonValueProcessor( beanClass, type, key ); if( jsonValueProcessor != null ){ value = jsonValueProcessor.processObjectValue( key, value, jsonConfig ); bypass = true; if( !JsonVerifier.isValidJsonValue( value ) ){ throw new JSONException( "Value is not a valid JSON value. " + value ); } } if( propertyNameProcessor != null ){ key = propertyNameProcessor.processPropertyName( beanClass, key ); } //设置属性值 setValue( jsonObject, key, value, type, jsonConfig, bypass ); }else{ String warning = "Property '" + key + "' of "+ beanClass+" has no read method. SKIPPED"; fireWarnEvent( warning, jsonConfig ); log.info( warning ); } } ....... }catch( JSONException jsone ){ removeInstance( bean ); fireErrorEvent( jsone, jsonConfig ); throw jsone; }catch( Exception e ){ removeInstance( bean ); JSONException jsone = new JSONException( e ); fireErrorEvent( jsone, jsonConfig ); throw jsone; } return jsonObject; }

    toBean(JSONObject object, Class clazz)方法

    由JSONObject对象转为对应类实例,关键代码在Object toBean( JSONObject jsonObject, JsonConfig jsonConfig )中,如下:

     public static Object toBean( JSONObject jsonObject, JsonConfig jsonConfig ) {

    if( jsonObject == null || jsonObject.isNullObject() ){
             return null;
          }
    
          Class beanClass = jsonConfig.getRootClass();//类对象
          Map classMap = jsonConfig.getClassMap();
    
          if( beanClass == null ){
             return toBean( jsonObject );
          }
          if( classMap == null ){
             classMap = Collections.EMPTY_MAP;
          }
    
          Object bean = null;
          try{
             if( beanClass.isInterface() ){
                if( !Map.class.isAssignableFrom( beanClass ) ){
                   throw new JSONException( "beanClass is an interface. " + beanClass );
                }else{
                   bean = new HashMap();
                }
             }else{
                bean = jsonConfig.getNewBeanInstanceStrategy() //实例化
                      .newInstance( beanClass, jsonObject );
             }
          }catch( JSONException jsone ){
             throw jsone;
          }catch( Exception e ){
             throw new JSONException( e );
          }
    
          Map props = JSONUtils.getProperties( jsonObject );//属性及属性类型  {name=class java.lang.String, age=class java.lang.Integer}
          PropertyFilter javaPropertyFilter = jsonConfig.getJavaPropertyFilter();
          for( Iterator entries = jsonObject.names( jsonConfig )
                .iterator(); entries.hasNext(); ){
             String name = (String) entries.next();//属性名
             Class type = (Class) props.get( name );//属性类型
             Object value = jsonObject.get( name );//属性值,如果属性值为null,返回的值为JSONNull对象
             if( javaPropertyFilter != null && javaPropertyFilter.apply( bean, name, value ) ){
                continue;
             }
             String key = Map.class.isAssignableFrom( beanClass )
                   && jsonConfig.isSkipJavaIdentifierTransformationInMapKeys() ? name
                   : JSONUtils.convertToJavaIdentifier( name, jsonConfig );
             PropertyNameProcessor propertyNameProcessor = jsonConfig.findJavaPropertyNameProcessor( beanClass );
             if( propertyNameProcessor != null ){
                key = propertyNameProcessor.processPropertyName( beanClass, key );
             }
             //设置实例对象的属性(处理各种情况)
             try{
                if( Map.class.isAssignableFrom( beanClass ) ){//Map对象单独处理
                   // no type info available for conversion
                   if( JSONUtils.isNull( value ) ){
                      setProperty( bean, key, value, jsonConfig );
                   }else if( value instanceof JSONArray ){
                      setProperty( bean, key, convertPropertyValueToCollection( key, value, jsonConfig, name,
                            classMap, List.class ), jsonConfig );
                   }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type )
                         || JSONUtils.isNumber( type ) || JSONUtils.isString( type )
                         || JSONFunction.class.isAssignableFrom( type ) ){
                      if( jsonConfig.isHandleJettisonEmptyElement() && "".equals( value ) ){
                         setProperty( bean, key, null, jsonConfig );
                      }else{
                         setProperty( bean, key, value, jsonConfig );
                      }
                   }else{
                      Class targetClass = resolveClass(classMap, key, name, type);
                      JsonConfig jsc = jsonConfig.copy();
                      jsc.setRootClass( targetClass );
                      jsc.setClassMap( classMap );
                      if( targetClass != null ){
                         setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig );
                      }else{
                         setProperty( bean, key, toBean( (JSONObject) value ), jsonConfig );
                      }
                   }
                }else{
                   PropertyDescriptor pd = PropertyUtils.getPropertyDescriptor( bean, key );//获取属性描述 
    //java.beans.PropertyDescriptor[name=name; propertyType=class java.lang.String; readMethod=public java.lang.String net.sf.json.mytest.Person.getName(); writeMethod=public void net.sf.json.mytest.Person.setName(java.lang.String)]
    if( pd != null && pd.getWriteMethod() == null ){ log.info( "Property '" + key + "' of "+ bean.getClass()+" has no write method. SKIPPED." ); continue; } if( pd != null ){ Class targetType = pd.getPropertyType(); if( !JSONUtils.isNull( value ) ){ if( value instanceof JSONArray ){ //JSONArray值 if( List.class.isAssignableFrom( pd.getPropertyType() ) ){ setProperty( bean, key, convertPropertyValueToCollection( key, value, jsonConfig, name, classMap, pd.getPropertyType() ), jsonConfig ); }else if( Set.class.isAssignableFrom( pd.getPropertyType() ) ){ setProperty( bean, key, convertPropertyValueToCollection( key, value, jsonConfig, name, classMap, pd.getPropertyType() ), jsonConfig ); }else{ setProperty( bean, key, convertPropertyValueToArray( key, value, targetType, jsonConfig, classMap ), jsonConfig ); } }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type ) //基本类型 || JSONUtils.isNumber( type ) || JSONUtils.isString( type ) || JSONFunction.class.isAssignableFrom( type ) ){ if( pd != null ){ if( jsonConfig.isHandleJettisonEmptyElement() && "".equals( value ) ){ setProperty( bean, key, null, jsonConfig ); }else if( !targetType.isInstance( value ) ){ setProperty( bean, key, morphPropertyValue( key, value, type, targetType ), jsonConfig ); }else{ setProperty( bean, key, value, jsonConfig );//对String进行处理 } }else if( beanClass == null || bean instanceof Map ){ setProperty( bean, key, value, jsonConfig ); }else{ log.warn( "Tried to assign property " + key + ":" + type.getName() + " to bean of class " + bean.getClass() .getName() ); } }else{ if( jsonConfig.isHandleJettisonSingleElementArray() ){ JSONArray array = new JSONArray().element( value, jsonConfig ); Class newTargetClass = resolveClass(classMap, key, name, type); JsonConfig jsc = jsonConfig.copy(); jsc.setRootClass( newTargetClass ); jsc.setClassMap( classMap ); if( targetType.isArray() ){ setProperty( bean, key, JSONArray.toArray( array, jsc ), jsonConfig ); }else if( JSONArray.class.isAssignableFrom( targetType ) ){ setProperty( bean, key, array, jsonConfig ); }else if( List.class.isAssignableFrom( targetType ) || Set.class.isAssignableFrom( targetType ) ){ jsc.setCollectionType( targetType ); setProperty( bean, key, JSONArray.toCollection( array, jsc ), jsonConfig ); }else{ setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig ); } }else{ if( targetType == Object.class || targetType.isInterface() ) { Class targetTypeCopy = targetType; targetType = findTargetClass( key, classMap ); targetType = targetType == null ? findTargetClass( name, classMap ) : targetType; targetType = targetType == null && targetTypeCopy.isInterface() ? targetTypeCopy : targetType; } JsonConfig jsc = jsonConfig.copy(); jsc.setRootClass( targetType ); jsc.setClassMap( classMap ); setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig ); } } }else{ if( type.isPrimitive() ){ // assume assigned default value log.warn( "Tried to assign null value to " + key + ":" + type.getName() ); setProperty( bean, key, JSONUtils.getMorpherRegistry() .morph( type, null ), jsonConfig ); }else{ setProperty( bean, key, null, jsonConfig ); } } }else{ // pd is null if( !JSONUtils.isNull( value ) ){ if( value instanceof JSONArray ){ setProperty( bean, key, convertPropertyValueToCollection( key, value, jsonConfig, name, classMap, List.class ), jsonConfig ); }else if( String.class.isAssignableFrom( type ) || JSONUtils.isBoolean( type ) || JSONUtils.isNumber( type ) || JSONUtils.isString( type ) || JSONFunction.class.isAssignableFrom( type ) ){ if( beanClass == null || bean instanceof Map || jsonConfig.getPropertySetStrategy() != null || !jsonConfig.isIgnorePublicFields() ){ setProperty( bean, key, value, jsonConfig ); }else{ log.warn( "Tried to assign property " + key + ":" + type.getName() + " to bean of class " + bean.getClass() .getName() ); } }else{ if( jsonConfig.isHandleJettisonSingleElementArray() ){ Class newTargetClass = resolveClass(classMap, key, name, type); JsonConfig jsc = jsonConfig.copy(); jsc.setRootClass( newTargetClass ); jsc.setClassMap( classMap ); setProperty( bean, key, toBean( (JSONObject) value, jsc ), jsonConfig ); }else{ setProperty( bean, key, value, jsonConfig ); } } }else{ if( type.isPrimitive() ){ // assume assigned default value log.warn( "Tried to assign null value to " + key + ":" + type.getName() ); setProperty( bean, key, JSONUtils.getMorpherRegistry() .morph( type, null ), jsonConfig ); }else{ setProperty( bean, key, null, jsonConfig ); } } } } }catch( JSONException jsone ){ throw jsone; }catch( Exception e ){ throw new JSONException( "Error while setting property=" + name + " type " + type, e ); } } return bean; }

     另外,Map转JSONObject问题:

    会将Map结构({key=value})转换为json格式(“key”:"value")。

    (1)java中的null,会转换为JSONNull对象,不能直接将该对象转为String。

    (2)net.sf.json.JSONObject不支持Map中key为null的情况。

    举例如下:

    import java.util.HashMap;
    import java.util.Map;
    
    import net.sf.json.JSONNull;
    import net.sf.json.JSONObject;
    
    public class Test {
    
        public static void main(String[] args) {
            Map<String, String> data1 = new HashMap<>();
    //        data1.put(null, "empty");  //报JSON keys cannot be null.
            data1.put("ts", null);
            System.out.println(data1.toString());
            if(data1.get("ts")==null){
                System.out.println("Map中的null");
            }
            
            JSONObject jsonObject = JSONObject.fromObject(data1);
            System.out.println(jsonObject.toString());
            
            if(JSONNull.getInstance().equals(jsonObject.get("ts"))){
                System.out.println("Map中的null,转为net.sf.json.JSONObject后,变成net.sf.json.JSONNull");
            }
            Map<String, Object> map = (Map<String, Object>) JSONObject.toBean(jsonObject, HashMap.class);
            System.out.println(map.get("ts").toString());
            
    //        Map<String, String> map = (Map<String, String>) JSONObject.toBean(jsonObject, HashMap.class);
    //        System.out.println(map.get("ts").toString()); //java.lang.ClassCastException: net.sf.json.JSONNull cannot be cast to java.lang.String
        }
    
    }

      结果:

    {ts=null}
    Map中的null
    {"ts":null}
    Map中的null,转为net.sf.json.JSONObject后,变成net.sf.json.JSONNull
  • 相关阅读:
    命令行添加subl命令
    mac 本地跨域
    ionic2 处理android硬件返回按钮
    ionic2 (真正)修改应用图标和启动画面
    ionic2 隐藏滚动条
    Tomcat在Eclips中的使用及注意细节
    JAVA解析xml的四种方式比较
    程序人生咖啡馆
    浅谈JAVA中HashMap、ArrayList、StringBuilder等的扩容机制
    mySQL 的 2个分类
  • 原文地址:https://www.cnblogs.com/shuimuzhushui/p/8901919.html
Copyright © 2011-2022 走看看