将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反序列化——日期转换的更多相关文章

  1. java中json和字符串互转及日期转换 练习

    一:以下是用到的jar名称: commons-beanutils-1.6.jar commons-collections-3.2.1.jar commons-lang-2.6.jar commons- ...

  2. 转:Json序列化和反序列化

    JSON是专门为浏览器中的网页上运行的JavaScript代码而设计的一种数据格式.在网站应用中使用JSON的场景越来越多,本文介绍 ASP.NET中JSON的序列化和反序列化,主要对JSON的简单介 ...

  3. Net中JSON序列化和反序列化处理(日期时间特殊处理)

    0  缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...

  4. json日期转换

    //调用 ChangeDateFormat(CreatTime) //json日期转换 function ChangeDateFormat(jsondate) { jsondate = jsondat ...

  5. Newtonsoft.Json日期转换

    在使用EasyUI做后台时,使用表格datagrid,用Newtonsoft.Json转换为Json格式后,时间显示为2013-06-15 T00:00:00形式. 后来研究了一下Newtonsoft ...

  6. Json序列化与反序列化(对象与Json字符串的转换)--C#

    public class JsonHelper { #region Json序列化与反序列化 /// <summary> /// 将json转化为对象 /// (需要提前构造好结构一致的M ...

  7. 05-06 Flutter JSON和序列化反序列化、创建模型类转换Json数据、轮播图数据渲染:Flutter创建商品数据模型 、请求Api接口渲染热门商品 推荐商品

    Config.dart class Config{ static String domain='http://jd.itying.com/'; } FocusModel.dart class Focu ...

  8. 使用JsonConfig控制JSON lib序列化

    将对象转换成字符串,是非常常用的功能,尤其在WEB应用中,使用 JSON lib 能够便捷地完成这项工作.JSON lib能够将Java对象转成json格式的字符串,也可以将Java对象转换成xml格 ...

  9. Newtonsoft.Json高级用法,json序列号,model反序列化,支持序列化和反序列化DataTable,DataSet,Entity Framework和Entity,字符串

    原文地址:https://www.cnblogs.com/yanweidie/p/4605212.html 手机端应用讲究速度快,体验好.刚好手头上的一个项目服务端接口有性能问题,需要进行优化.在接口 ...

随机推荐

  1. Jupyter Notebook不能自动打开浏览器

    安装了 Winpython,运行Jupyter Notebook.exe或Jupyter lab.exe,总是不能自动打开浏览器,提示"no web browser found" ...

  2. PostMan 中使用Datas 文件一次Run 只能使用一个

    PostMan 一次run  只能有一个文件. Note that you can only use one data file for one run.

  3. Web开发的分层结构与MVC模式

    1.分层结构 所谓分层结构.把不同的功能代码封装成类,把相同功能的类封装在一个个的包中,也叫层.功能归类如下: 实体类: 封装数据,是数据的载体,在层与层之间进行传递,数据也就传递了.比如说要传递学生 ...

  4. mysql 中的 tinyint 字段

    只能存储  -128 ~ 127  之间的数字

  5. 百度云直线在线解析+xdown

    一:在浏览器打开百度云分享链接(推荐Google)百度云分享的链接:https://pan.baidu.com/s/17YQ2x--kOAa_hpapaTcq8Q第二步:打开直线在线解析:https: ...

  6. Type反射遍历类的属性

    <?xml version="1.0" encoding="utf-8" ?> <configuration> <startup& ...

  7. 延长zencart1.5.x后台的15分钟登录时间和取消90天强制更换密码

    延长zencart1.5.x后台的15分钟登录时间 打开includes\functions\sessions.php if (IS_ADMIN_FLAG === true) { if (!$SESS ...

  8. unbutu apt-get update失败及解决办法

    今天在用apt-get update更新时一直失败,报的错误为”Failed to fetch 404 Not Found”,因为我的镜像改为了mirrors.aliyun.com 我试着ping了一 ...

  9. Mybatis XML配置(转载)

    原文地址:https://www.w3cschool.cn/mybatis/f4uw1ilx.html Mapper XML 文件 MyBatis 的真正强大在于它的映射语句,也是它的魔力所在.由于它 ...

  10. web.xml中<welcome-file-list>标签不起作用

    之前也都提到过,web.xml会通过<servlet>和<servlet-mapping>来确定url和指定contoller文件,乃至于jsp页面的联系. 但是有一个< ...