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. vue初尝试--项目结构

    新建一个项目之后,我们来看一下项目的目录结构 几个主要文件的内容 index.html文件(入口文件,系统进入之后先进入index.html) <!DOCTYPE html> <ht ...

  2. Java可重入锁如何避免死锁

    本文由https://bbs.csdn.net/topics/390939500和https://zhidao.baidu.com/question/1946051090515119908.html启 ...

  3. MapReduce工作机制——Word Count实例(一)

    MapReduce工作机制--Word Count实例(一) MapReduce的思想是分布式计算,也就是分而治之,并行计算提高速度. 编程思想 首先,要将数据抽象为键值对的形式,map函数输入键值对 ...

  4. MHA 安装与简单使用

    MHA 在过去几年一直用的比较火,特别是在在传统复制的那个年代.至从有了GTID好像我们也可以把MHA给忘记了,但是很多企业现在还是在用的比较多.每个公司的MHA玩法也不太一样,但是本质都是差不多了. ...

  5. Python内置函数(59)——open

    英文文档: open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, ope ...

  6. Spring Security入门(3-2)Spring Security对接用户的权限系统

    源文链接,多谢作者的分享: http://www.360doc.com/content/14/0727/16/18637323_397445724.shtml 1.原生的spring-security ...

  7. 前端开发必备之Chrome开发者工具(一)

    本文介绍的 Chrome 开发者工具基于 Chrome 65版本,如果你的 Chrome 开发者工具没有下文提到的那些内容,请检查下 Chrome 的版本 简介 Chrome 开发者工具是一套内置于 ...

  8. python网络编程基础(一)

    一.C/S架构 客户端/服务端架构 二.OSI七层架构 七层模型,亦称OSI(Open System Interconnection)参考模型,是参考模型是国际标准化组织(ISO)制定的一个用于计算机 ...

  9. MongDB配置方法

    先下载安装包 安装 方法一:命令行启动 在 C:\MongoDB\Server\3.4目录下建立data文件夹, data里面建立db文件夹 bin目录下运行 mongod --dbpath C:\M ...

  10. css常见属性

    css常见属性 1.颜色属性 1.1 color属性定义文本的颜色 1.2 color:green 1.3 color:#ff6600 可简写为#f60 1.4 color:rgb(255,255,2 ...