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 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...
随机推荐
- XML基础综合案例【三】
实现简单的学生管理系统 使用xml当做数据,存储学生信息 ** 创建一个xml文件,写一些学生信息 ** 增加操作1.创建解析器2.得到document 3.获取到根节点4.在根节点上面创建stu标签 ...
- 04-【servlet转发和重定向】
转发: //forward(将 数据传给下一个资源(servlet,jsp ,html等 ,把请求和响应的数据和参数设置带过去 ) request.getRequestDispatcher(" ...
- deep_learning_Function_reduction_indices的用法
在tf.reduce_sum等函数中,有一个reduction_indices参数,表示函数的处理维度. 当没有reduction_indices这个参数,此时该参数取默认值None,将把input_ ...
- python常用模块:项目目录规范、定制程序入口、自定义模块、引用变量、time和datetime模块
今天讲课内容有两大部分: 一.文件目录规范二.定制程序入口三.使用标准目录后四.常规函数time.datetime 一.标准目录规范 之前用过的案例atm机+购物商城代码过长,在学习了模块和包以后,我 ...
- python 示例代码2
示例2:变量赋值,打印拼接(var.py) 变量定义的规则: 变量名只能是字母.数字或下划线的任意组合 变量名的第一个字符不能是数字 以下关键字不能声明为变量名 ['and', 'as', 'asse ...
- Java运行环境绿色部署配置
这个Java的绿色安装配置,还有从未自己的使用电脑说起来. 最近电脑运行慢,很长时间没有清理及维护了,而且有可能中毒或木马了,所以就把系统进行了Ghost还原了,所以原来安装的jdk环境也无法使用了, ...
- Apache代理技术
Apache代理技术 apache代理分为正向代理和反向代理. 正向代理是一个位于客户端和原始服务器之间的服务器, 客户端通过代理服务器访问外部的 web, 需要在客户端的浏览器中设置代理服务器. 反 ...
- 不使用C库函数(Sprintf)将void* 指针转换为十六进制字符串
#include <stdio.h> #include <stdint.h> #include <stdlib.h> void hexDump(void *ptr, ...
- TensorFlow - 深度学习破解验证码 实验
TensorFlow - 深度学习破解验证码 简介:验证码主要用于防刷,传统的验证码识别算法一般需要把验证码分割为单个字符,然后逐个识别,如果字符之间相互重叠,传统的算法就然并卵了,本文采用cnn对验 ...
- gradle——入门
为脚本中自定义变量传参: gradle -Pmyprop=myvalue 脚本攻略 https://blog.csdn.net/yanbober/article/details/49314255 强制 ...