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
JSONObject转换分析的更多相关文章
- Linux网络地址转换分析
Linux网络地址转换分析 地址转换用来改变源/目的端口,是netfilter的一部分,也是通过hook点上注册相应的结构来工作. Nat注册的hook点和conntrack相同,只是优先级不同,数据 ...
- Java线程Thread的状态解析以及状态转换分析 多线程中篇(七)
线程与操作系统中线程(进程)的概念同根同源,尽管千差万别. 操作系统中有状态以及状态的切换,Java线程中照样也有. State 在Thread类中有内部类 枚举State,用于抽象描述Java线程的 ...
- JSONObject转换Int类型--java.lang.Integer cannot be cast to java.lang.String
参数 params={"abc":0} JSONObject转换Int类型 JSONObject json = JSONObject.fromObject(params); if ...
- JSONObject转换JSON--将Date转换为指定格式
项目中,经常会用JSONObject插件将JavaBean或List<JavaBean>转换为JSON格式的字符串,而JavaBean的属性有时候会有java.util.Date这个类型的 ...
- JSONObject转换JSON之将Date转换为指定格式(转)
项目中,经常会用JSONObject插件将JavaBean或List<JavaBean>转换为JSON格式的字符串,而JavaBean的属性有时候会有java.util.Date这个类型的 ...
- Android MediaCodec 状态(States)转换分析
*由于工作需要,需要利用MediaCodec实现Playback及Transcode等功能,故在学习过程中翻译了Google官方的MediaCodec API文档,由于作者水平限制,文中难免有错误和不 ...
- JSONObject 转换 JSON复杂对象
Bean定义: public class GetM100DataResponse { private String service;//接口代码 private String sessionId;// ...
- ffmpeg转换参数和对几种视频格式的转换分析
我们在将多种格式的视频转换成flv格式的时候,我们关注的就是转换后的flv视频的品质和大小.下面就自己的实践所得来和大家分享一下,主要针对avi.3gp.mp4和wmv四种格式来进行分析.通常在使用f ...
- 将JsonObject转换成HashMap
1.工具类: Utils.class: (1)简单的键值对map public class Utils { public static String getRaw(Context context, i ...
随机推荐
- Scala 集合入门
1. 数组 1.1 定长数组 scala.Array 是定长的可变的索引型集合, JVM 中, Scala 的 Array 是以 Java 数组方式实现. String 对应 java.lang.St ...
- Linq 集合操作符 Except,Intersect,Union
IList<string> s1 = new List<string>() { "One", "Two", "Three&qu ...
- linux下执行java类(运行java定时器)
假如有一个定时器TimerTest.java import java.io.IOException; import java.util.Timer; public class TimerTest { ...
- hadoop2.6.0理论:hdfs、yarn、mapreduce的架构
HDFS2的架构:负责数据的分布式存储 主从结构 主节点,可以有2个: namenode 从节点,有很多个: datanode namenode负责: 接收用户操作请求,是用户操作的入口 维护文件系统 ...
- Django REST framework+Vue 打造生鲜超市(四)
五.商品列表页 5.1.django的view实现商品列表页 (1)goods/view_base.py 在goods文件夹下面新建view_base.py,为了区分django和django res ...
- Ecplise 配置本地 https 测试
今天做项目,需要关联Office 365.为了实现Office365的用户邮件信息与项目的实时同步,需要建立webhook订阅. Office 365 API 连接 https://graph.mi ...
- .net core 使用阿里云短信发送SMS
阿里云官方的skd(aliyun-net-sdk-core,aliyun-net-sdk-dysmsapi)在dnc中发送短信会出错,nuget上的包貌似也一样不管用.直接改下sdk当然也可以,但就发 ...
- python操作mongodb
# python操作mongodb # 首先,引入第三方模块pymongo,该模块是python用来操作mongodb的 import pymongo # 第二步,设置ip地址,以及表格名称,表格名字 ...
- find()用法
>>> str = '编程改变世界'>>> str.find('编')0>>> str.find('程')1>>> str.fi ...
- 使用Navicat Premium 链接本地数据库的方法(二)
最早一篇:http://www.cnblogs.com/zhengyeye/p/6363179.html 现在又重新装了电脑系统,需遇到了同样的问题.恰巧记得之前自己写的文档,没准可以帮助自己解决掉这 ...