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

JSONObject转换分析的更多相关文章

  1. Linux网络地址转换分析

    Linux网络地址转换分析 地址转换用来改变源/目的端口,是netfilter的一部分,也是通过hook点上注册相应的结构来工作. Nat注册的hook点和conntrack相同,只是优先级不同,数据 ...

  2. Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)

    线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...

  3. JSONObject转换Int类型--java.lang.Integer cannot be cast to java.lang.String

    参数 params={"abc":0} JSONObject转换Int类型 JSONObject json = JSONObject.fromObject(params); if ...

  4. JSONObject转换JSON--将Date转换为指定格式

    项目中,经常会用JSONObject插件将JavaBean或List<JavaBean>转换为JSON格式的字符串,而JavaBean的属性有时候会有java.util.Date这个类型的 ...

  5. JSONObject转换JSON之将Date转换为指定格式(转)

    项目中,经常会用JSONObject插件将JavaBean或List<JavaBean>转换为JSON格式的字符串,而JavaBean的属性有时候会有java.util.Date这个类型的 ...

  6. Android MediaCodec 状态(States)转换分析

    *由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...

  7. JSONObject 转换 JSON复杂对象

    Bean定义: public class GetM100DataResponse { private String service;//接口代码 private String sessionId;// ...

  8. ffmpeg转换参数和对几种视频格式的转换分析

    我们在将多种格式的视频转换成flv格式的时候,我们关注的就是转换后的flv视频的品质和大小.下面就自己的实践所得来和大家分享一下,主要针对avi.3gp.mp4和wmv四种格式来进行分析.通常在使用f ...

  9. 将JsonObject转换成HashMap

    1.工具类: Utils.class: (1)简单的键值对map public class Utils { public static String getRaw(Context context, i ...

随机推荐

  1. Winserver+Apache+django部署

    废话不多说,干活直接上. winserver2012 + django2.0.1 + apache 部署过程 python ==> 3.4 64位 https://www.python.org/ ...

  2. python小练习之一

    下面的练习本身不难,比如打印1到10,计算1+2+3+...+100 ,最后一个是计算 1-2+3-4...-100 用了类的方法实现 用了列表生成器 用"高级"一丢丢的写法来实现 ...

  3. machine learning 之 导论 一元线性回归

    整理自Andrew Ng 的 machine learnig 课程 week1. 目录: 什么是机器学习 监督学习 非监督学习 一元线性回归 模型表示 损失函数 梯度下降算法 1.什么是机器学习 Ar ...

  4. MySQL“Another MySQL daemon already running with the same unix socket” 报错信息处理

    Mysql "Another Mysql daemon already running with the same unix socket" 解决办法:rm var/lib/mys ...

  5. 第一章 jQuery基础

    第一章jQuery基础 一.jQuert简介 1.什么是jQuery jQuery是javaScript的程序库之一,它是javaScript对象和实用函数的封装. jQuery是继Prototype ...

  6. Extensions in UWP Community Toolkit - Overview

    概述 UWP Community Toolkit  中有一个 Extensions 的集合,它们可以帮助开发者实现很多基础功能,省去自己造轮子的过程,本篇我们先来看一下 Extensions 的功能都 ...

  7. SSH 配置

    ssh免密通用配置 Host * Port 1234 User root #ProxyCommand nc -X 5 -x 127.0.0.1:1081 %h %p #5 socks5, 4 sock ...

  8. 阿里云下Linux服务器安装Mysql、mongodb

    阿里云下Linux服务器安装Mysql.mongodb 一.MySQL的安装和配置 1.安装rpm包 rpm -Uvh http://dev.mysql.com/get/mysql-community ...

  9. Django知识总结

    一.什么是web框架? 框架,即framework,特指为解决一个开放性问题而设计的具有一定约束性的支撑结构,使用框架可以帮你快速开发特定的系统,简单地说,就是你用别人搭建好的舞台来做表演. web应 ...

  10. python自定义函数可以向前引用不用声明

    #有些编程语言不够"聪明",向这类向前引用的方式会导致报错,但Python足够"醒目",这段代码是正确的! def next():     print('我在n ...