json-lib json反序列化——日期转换
将json格式的字符串转为对象,其中key-value有将String的日期转为Date类型,怪现象就是,转出来的Date类型的值是当前的系统时间。
网上有许多答案,在反序列化之前需要注册Date解析类型,也就是这段代码:
JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[]{"yyyy-MM-dd"}));
发现并没啥用,最后发现一切的原因都是因为这个方法用错了。
仔细看源码,原来在json-lib中一个MorpherRegistry类,所有的转化类型都存在Map morphers中。
在第一次使用JSONObject静态方法时,就会自动注册默认的类型,JSONObject.java中调用了JSONUtils.java,JSONUtils.java源码中有这么一段:
static {
    MorphUtils.registerStandardMorphers(morpherRegistry);
}
在MorphUtils.java代码是:
 public class MorphUtils {
     public static final BigDecimal BIGDECIMAL_ONE = new BigDecimal("1");
     public static final BigDecimal BIGDECIMAL_ZERO = new BigDecimal("0");
     public static void registerStandardMorphers(MorpherRegistry morpherRegistry) {
         morpherRegistry.clear();
         registerStandardPrimitiveMorphers(morpherRegistry);
         registerStandardPrimitiveArrayMorphers(morpherRegistry);
         registerStandardObjectMorphers(morpherRegistry);
         registerStandardObjectArrayMorphers(morpherRegistry);
     }
     public static void registerStandardObjectArrayMorphers(MorpherRegistry morpherRegistry) {
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new BooleanObjectMorpher(Boolean.FALSE)));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new CharacterObjectMorpher(new Character('\u0000'))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(StringMorpher.getInstance()));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Byte.class, new Byte((byte)0))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Short.class, new Short((short)0))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Integer.class, new Integer(0))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Long.class, new Long(0L))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Float.class, new Float(0.0F))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(Double.class, new Double(0.0D))));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(BigInteger.class, BigInteger.ZERO)));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(new NumberMorpher(BigDecimal.class, BIGDECIMAL_ZERO)));
         morpherRegistry.registerMorpher(new ObjectArrayMorpher(ClassMorpher.getInstance()));
     }
     public static void registerStandardObjectMorphers(MorpherRegistry morpherRegistry) {
         morpherRegistry.registerMorpher(new BooleanObjectMorpher(Boolean.FALSE));
         morpherRegistry.registerMorpher(new CharacterObjectMorpher(new Character('\u0000')));
         morpherRegistry.registerMorpher(StringMorpher.getInstance());
         morpherRegistry.registerMorpher(new NumberMorpher(Byte.class, new Byte((byte)0)));
         morpherRegistry.registerMorpher(new NumberMorpher(Short.class, new Short((short)0)));
         morpherRegistry.registerMorpher(new NumberMorpher(Integer.class, new Integer(0)));
         morpherRegistry.registerMorpher(new NumberMorpher(Long.class, new Long(0L)));
         morpherRegistry.registerMorpher(new NumberMorpher(Float.class, new Float(0.0F)));
         morpherRegistry.registerMorpher(new NumberMorpher(Double.class, new Double(0.0D)));
         morpherRegistry.registerMorpher(new NumberMorpher(BigInteger.class, BigInteger.ZERO));
         morpherRegistry.registerMorpher(new NumberMorpher(BigDecimal.class, BIGDECIMAL_ZERO));
         morpherRegistry.registerMorpher(ClassMorpher.getInstance());
     }
     public static void registerStandardPrimitiveArrayMorphers(MorpherRegistry morpherRegistry) {
         morpherRegistry.registerMorpher(new BooleanArrayMorpher(false));
         morpherRegistry.registerMorpher(new CharArrayMorpher('\u0000'));
         morpherRegistry.registerMorpher(new ByteArrayMorpher((byte)0));
         morpherRegistry.registerMorpher(new ShortArrayMorpher((short)0));
         morpherRegistry.registerMorpher(new IntArrayMorpher(0));
         morpherRegistry.registerMorpher(new LongArrayMorpher(0L));
         morpherRegistry.registerMorpher(new FloatArrayMorpher(0.0F));
         morpherRegistry.registerMorpher(new DoubleArrayMorpher(0.0D));
     }
     public static void registerStandardPrimitiveMorphers(MorpherRegistry morpherRegistry) {
         morpherRegistry.registerMorpher(new BooleanMorpher(false));
         morpherRegistry.registerMorpher(new CharMorpher('\u0000'));
         morpherRegistry.registerMorpher(new ByteMorpher((byte)0));
         morpherRegistry.registerMorpher(new ShortMorpher((short)0));
         morpherRegistry.registerMorpher(new IntMorpher(0));
         morpherRegistry.registerMorpher(new LongMorpher(0L));
         morpherRegistry.registerMorpher(new FloatMorpher(0.0F));
         morpherRegistry.registerMorpher(new DoubleMorpher(0.0D));
     }
     private MorphUtils() {
     }
 }
因此,在JSONUtils初始化的时候,就将默认类型放在了MorpherRegistry的morphs中。从上面的代码可以看出来,Date不属于默认的类型。因此,这里可以看出来,在做json反序列化时,如果有需要转成Date类型的String,就需要自己手动注册一个DateMorpher。
怎么加是一个问题了。其实在文章最前面提到的网上的解决方案也并没有错,看下源码就知道了,为啥这个方法却在我使用的时候不起作用了。
在MorpherRegistry.java中Morpher注册源码:
 public class MorpherRegistry implements Serializable {
     private static final long serialVersionUID = -3894767123320768419L;
     private Map morphers = new HashMap();
     public MorpherRegistry() {
     }
     public synchronized Morpher[] getMorphersFor(Class clazz) {
         List registered = (List)this.morphers.get(clazz);
         if(registered != null && !registered.isEmpty()) {
             Morpher[] morphs = new Morpher[registered.size()];
             int k = 0;
             for(Iterator i = registered.iterator(); i.hasNext(); morphs[k++] = (Morpher)i.next()) {
                 ;
             }
             return morphs;
         } else {
             return new Morpher[]{IdentityObjectMorpher.getInstance()};
         }
     }
     public Object morph(Class target, Object value) {
         if(value == null) {
             Morpher var9 = this.getMorpherFor(target);
             if(var9 instanceof ObjectMorpher) {
                 return ((ObjectMorpher)var9).morph(value);
             } else {
                 try {
                     Method var10 = var9.getClass().getDeclaredMethod("morph", new Class[]{class$java$lang$Object == null?(class$java$lang$Object = class$("java.lang.Object")):class$java$lang$Object});
                     return var10.invoke(var9, new Object[]{value});
                 } catch (Exception var7) {
                     throw new MorphException(var7);
                 }
             }
         } else {
             Morpher[] morphers = this.getMorphersFor(target);
             for(int i = 0; i < morphers.length; ++i) {
                 Morpher morpher = morphers[i];
                 if(morpher.supports(value.getClass())) {
                     if(morpher instanceof ObjectMorpher) {
                         return ((ObjectMorpher)morpher).morph(value);
                     }
                     try {
                         Method e = morpher.getClass().getDeclaredMethod("morph", new Class[]{class$java$lang$Object == null?(class$java$lang$Object = class$("java.lang.Object")):class$java$lang$Object});
                         return e.invoke(morpher, new Object[]{value});
                     } catch (Exception var8) {
                         throw new MorphException(var8);
                     }
                 }
             }
             return value;
         }
     }
     public synchronized void registerMorpher(Morpher morpher, boolean override) {
         Object registered = (List)this.morphers.get(morpher.morphsTo());
         if(override || registered == null) {
             registered = new ArrayList();
             this.morphers.put(morpher.morphsTo(), registered);
         }
         if(!((List)registered).contains(morpher)) {
             ((List)registered).add(morpher);
         }
     }
 }
在registerMorpher()中,可以看出来morpher事实上是一个Map<Object.class, List<Morpher>>的结构,而在使用morph()将String转为对象时取得是最先符合的类型。因此,前文中提到提到的网络解决方法,在morpher.get(Object.class)不为空时,只是对List<Morpher> registered进行add操作。由此,在进行转化操作时,就不一定获取到正确的对应类型。因此从registerMorpher()方法中可以看出,我们只需要override设置为false,这个问题也就解决了。
假如我们在调试的时候,需要修改这个注册类型,且又不想重启服务的时候,这样写就很方便了。
JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(new String[]{"yyyy-MM-dd"}), true);
这样就能获取到正确的转化类型。
前文还提到一个问题,就是时间转化,变成了当前系统的时间。在MorpherRegistry进行反序列时,morph()中
((ObjectMorpher)morpher).morph(value)
调用的方法是BeanMorpher.morph方法,在BeanMorpher.morp()方法中
 public Object morph(Object sourceBean) {
         if(sourceBean == null) {
             return null;
         } else if(!this.supports(sourceBean.getClass())) {
             throw new MorphException("unsupported class: " + sourceBean.getClass().getName());
         } else {
             Object targetBean = null;
             try {
                 targetBean = this.beanClass.newInstance();
                 PropertyDescriptor[] e = PropertyUtils.getPropertyDescriptors(this.beanClass);
                 for(int i = 0; i < e.length; ++i) {
                     PropertyDescriptor targetPd = e[i];
                     String name = targetPd.getName();
                     if(targetPd.getWriteMethod() == null) {
                         log.info("Property \'" + this.beanClass.getName() + "." + name + "\' has no write method. SKIPPED.");
                     } else {
                         Class sourceType = null;
                         if(sourceBean instanceof DynaBean) {
                             DynaBean targetType = (DynaBean)sourceBean;
                             DynaProperty value = targetType.getDynaClass().getDynaProperty(name);
                             if(value == null) {
                                 log.warn("DynaProperty \'" + name + "\' does not exist. SKIPPED.");
                                 continue;
                             }
                             sourceType = value.getType();
                         } else {
                             PropertyDescriptor var12 = PropertyUtils.getPropertyDescriptor(sourceBean, name);
                             if(var12 == null) {
                                 log.warn("Property \'" + sourceBean.getClass().getName() + "." + name + "\' does not exist. SKIPPED.");
                                 continue;
                             }
                             if(var12.getReadMethod() == null) {
                                 log.warn("Property \'" + sourceBean.getClass().getName() + "." + name + "\' has no read method. SKIPPED.");
                                 continue;
                             }
                             sourceType = var12.getPropertyType();
                         }
                         Class var13 = targetPd.getPropertyType();
                         Object var14 = PropertyUtils.getProperty(sourceBean, name);
                         this.setProperty(targetBean, name, sourceType, var13, var14);
                     }
                 }
                 return targetBean;
             } catch (MorphException var10) {
                 throw var10;
             } catch (Exception var11) {
                 throw new MorphException(var11);
             }
         }
     }
sourceBean不属于DynaBean,且var12的值也为null,因此返回的值就是targetBean,时间的一个实例,即当前时间。
json-lib json反序列化——日期转换的更多相关文章
- java中json和字符串互转及日期转换 练习
		一:以下是用到的jar名称: commons-beanutils-1.6.jar commons-collections-3.2.1.jar commons-lang-2.6.jar commons- ... 
- 转:Json序列化和反序列化
		JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介 ... 
- Net中JSON序列化和反序列化处理(日期时间特殊处理)
		0 缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ... 
- json日期转换
		//调用 ChangeDateFormat(CreatTime) //json日期转换 function ChangeDateFormat(jsondate) { jsondate = jsondat ... 
- Newtonsoft.Json日期转换
		在使用EasyUI做后台时,使用表格datagrid,用Newtonsoft.Json转换为Json格式后,时间显示为2013-06-15 T00:00:00形式. 后来研究了一下Newtonsoft ... 
- Json序列化与反序列化(对象与Json字符串的转换)--C#
		public class JsonHelper { #region Json序列化与反序列化 /// <summary> /// 将json转化为对象 /// (需要提前构造好结构一致的M ... 
- 05-06 Flutter JSON和序列化反序列化、创建模型类转换Json数据、轮播图数据渲染:Flutter创建商品数据模型 、请求Api接口渲染热门商品 推荐商品
		Config.dart class Config{ static String domain='http://jd.itying.com/'; } FocusModel.dart class Focu ... 
- 使用JsonConfig控制JSON lib序列化
		将对象转换成字符串,是非常常用的功能,尤其在WEB应用中,使用 JSON lib 能够便捷地完成这项工作.JSON lib能够将Java对象转成json格式的字符串,也可以将Java对象转换成xml格 ... 
- Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串
		原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ... 
随机推荐
- Java List集合深入学习
			List: https://blog.csdn.net/qq_37939251/article/details/83499291 https://blog.csdn.net/weixin_403043 ... 
- centos 7 OpenResty®(lua-nginx-module)搭建可扩展的Web平台
			OpenResty®-英文官网地址:http://openresty.org/en/ OpenResty®-中文官网地址: http://openresty.org/cn/ OpenResty®> ... 
- 【转】container_of宏 分析
			在学习Linux驱动的过程中,遇到一个宏叫做container_of.该宏定义在include/linux/kernel.h中,首先来贴出它的代码: /** * container_of - cast ... 
- MySQL介绍及安装环境配置
			MySQL介绍及安装环境配置 MySQL是一种关系数据库管理系统,是一种开源软件.由瑞典MySQL AB公司开发,2008年1月16号被Sun公司收购.2009年,SUN又被Oracle收购.MySQ ... 
- windows消息的循环机制
			首先来了解几个基本概念: 消息:在了解什么是消息先来了解什么是事件.事件可分为几种,由输入设备触发的,比如鼠标键盘等等.由窗体控件触发的,比如button控件,file菜单等.还有就是来自Window ... 
- Activity的跳转及返回值,activity的生命周期
			Activity生命周期 从创建到销毁的生命周期: onCreate()→onStart()→onResume()→onPouse()→onStop()→onDestroy() 从起动到后台再到前台: ... 
- Linux配置JDK环境
			wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-co ... 
- springboot的一些开源项目
			原文标题:精选SpringBoot八大开源项目:支付.秒杀.全文搜索等 支付项目: 项目地址:https://gitee.com/52itstyle/spring-boot-pay 秒杀案例: 项目地 ... 
- Linux日常之命令awk
			参考:http://www.zsythink.net/archives/tag/awk/ 一. 命令awk简介 1. awk是一种编程语言,用于对文本和数据进行处理的 2. 具有强大的文本格式化能力 ... 
- solr 倒排索引(转载)
			原文地址:http://blog.csdn.net/chichengit/article/details/9235157 http://blog.csdn.net/njpjsoftdev/articl ... 
