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 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...
随机推荐
- Centos 7.0 界面
执行:systemctl get-default //显示默认的界面方式 multi-user.target //命令行界面 graphical.target //图形化界面 执行:systemctl ...
- 蓝牙App漏洞系列分析之三CVE-2017-0645
蓝牙App漏洞系列分析之三CVE-2017-0645 0x01 漏洞简介 Android 6月的安全公告,同时还修复了我们发现的一个蓝牙 App 提权中危漏洞,该漏洞允许手机本地无权限的恶意程序构造一 ...
- STM32定义变量位于指定的SRAM地址
1.定义一个数组比如value[],让数组的首地址指向特定的SRAM地址,比如0x20000100 1)__align(8) uint8_t value[20] __attribute__((at(0 ...
- QTP(16)
一.QTP项目(ECShop) 1.ECShop是一个开源免费的一个B2C的电子商务系统,主要用于商家和顾客进行商品交易操作. 2.ECShop分为前台和后台两个子系统: (1)ECShop前台:顾客 ...
- sql 178. 分数排名
编写一个 SQL 查询来实现分数排名.如果两个分数相同,则两个分数排名(Rank)相同.请注意,平分后的下一个名次应该是下一个连续的整数值.换句话说,名次之间不应该有“间隔”. +----+----- ...
- SQL Server中四类事务并发问题的实例再现(转)
本篇文章将用实例再现数据库访问中四类并发问题,希望能让初学者能对事务的并行性有进一步的理解. 首先,让我们先来了解一下并行问题以及事务隔离级别这两个概念.在数据库中,假设如果没有锁定且多个用户同时访问 ...
- 关于JavaScript的事件绑定
js事件绑定的几种方式 JavaScript中有三种常用的绑定事件方法: 1. 在DOM元素中直接绑定: 2. 在JavaScript代码中绑定: 3. 绑定事件佳妮婷函数. 一.在DOM元素中直接绑 ...
- 开启防火墙如何部署k8s
你可以不关闭防火墙,只需要开启这些端口就行了MASTER节点6443* Kubernetes API server 2379-2380 etcd server client API 10250 Kub ...
- es6 模块编译 *** is not function
今天学习vuejs,里面用到了es6的写法,遇到了一个很怪的问题,不知道有人遇到么. 安装的模块引用:import Vue from 'vue';(注意,Vue处没有{},如果加上这个就报错Uncau ...
- HDU-3746-Cyclic nacklace(KMP, 循环节)
链接: https://vjudge.net/problem/HDU-3746 题意: 第一题来啦. 现在给你一个字符串,请问在该字符串末尾最少添加多少个字符,可以让这个字符串获得重复循环序列. 思路 ...