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 ...
随机推荐
- Gson解析Json数组
需求:从steam官网获取英雄数据,即为Json数据,并导入到本地数据库 Json数据是这样的 { "result": { "heroes": [ { &quo ...
- SQL SERVER 游标的使用
首先,关于什么是游标大家可以看看这篇文章,介绍得非常详细!! SQL Server基础之游标 下面是我自己的应用场景-- 有个需求,需要把数据库表里面某一个字段的值设为随机不重复的值. 表是这样的: ...
- 剑指offer-第一个只出现一次的字符
题目描述 在一个字符串(1<=字符串长度<=10000,全部由字母组成)中找到第一个只出现一次的字符,并返回它的位置 解题思路 由于char类型一共有256种可能,所以开辟一个数组ha ...
- Win10安装Ubuntu14.04.5双系统(显示器为DP接口)
系统安装主要参考了这篇博文Win10+Ubuntu17.04双系统安装,不再重复. 重点说说DP接口的事,如果主机有VGA接口的话可以到此为止了,如果只有DP接口的话可以参考以下内容. 一.Ubunt ...
- C#Json转DataTable
需求:有一个log文件,需要整理成Excel,日志文件里面的数据都是json字符串 思路是,把Json字符串转换成DataTable,然后导出到Excel 在网上找了一些资料,整理了以下三种类型的Js ...
- Modelsim的使用——复杂的仿真
相对于简单的仿真,复杂的仿真是指由多个文件.甚至调用了IP核.使用tcl脚本进行的仿真.其实仿真步骤跟图形化的差不多,只不过每一步用脚本写好,然后再在软件里面run一下,主要过程就是: 1.准备好各种 ...
- hdu1072 Nightmare---BFS
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1072 题目大意: 在n×m的地图上,0表示墙,1表示空地,2表示人,3表示目的地,4表示有定时炸弹重 ...
- asp.net core 六 Oracle ORM
.netcore 中 Oracle ORM 在真正将项目移植到.netcore下,才发现会有很多问题,例如访问Oracle,问题出现的时间在2017年底 参考连接 ...
- Item Pipeline
当Item在Spider中被收集之后,它将会被传递到Item Pipeline,一些组件会按照一定的顺序执行对Item的处理. 每个item pipeline组件(有时称之为"Item Pi ...
- JavaScript splice() 、slice() 方法
定义和用法 splice() 方法向/从数组中添加/删除项目,然后返回被删除的项目. slice() 方法可从已有的数组中返回选定的元素. 注释:该方法会改变原始数组. 语法 arrayObject. ...