需求:

在我们的项目里希望JsonString传入日期类型值为空时,JSONObject.toBean时可以将Java对象的该日期属性设为null。

解决过程:

json-lib反序列化Json字符串为Java对象,可以通过以下代码处理日期字段:

 public static <T> T JsonToBean(Class<T> clazz, String JsonString) {
JSONUtils.getMorpherRegistry().registerMorpher(
new DateMorpher(new String[] { "yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd", "yyyy-MM-dd't'HH:mm:ss" }));
JSONObject jsonObject = JSONObject.fromObject(JsonString);
T entity = (T) JSONObject.toBean(jsonObject, clazz);
return entity;
}

但如果JsonString传入{"createDate":""}时,则会在“T entity = (T) JSONObject.toBean(jsonObject, clazz)”时报以下错误:

net.sf.json.JSONException: Error while setting property=createDate type class java.lang.String

查看net.sf.ezmorph.object.DateMorpher方法的源码,关于字符串转时间的代码如下:

       public Object morph(Object value)
{
if (value == null) {
return null;
} if (Date.class.isAssignableFrom(value.getClass())) {
return (Date)value;
} if (!supports(value.getClass())) {
throw new MorphException(value.getClass() + " is not supported");
} String strValue = (String)value;
SimpleDateFormat dateParser = null; for (int i = 0; i < this.formats.length; ++i) {
if (dateParser == null)
dateParser = new SimpleDateFormat(this.formats[i], this.locale);
else {
dateParser.applyPattern(this.formats[i]);
}
dateParser.setLenient(this.lenient);
try {
return dateParser.parse(strValue.toLowerCase());
}
catch (ParseException localParseException)
{
}
} if (super.isUseDefault()) {
return this.defaultValue;
}
throw new MorphException("Unable to parse the date " + value);
}

可以看到,在18~32行会使用我们传入的formats循环进行字符串转换,如果转换成功则返回Date,如果全部失败则在37行处抛出异常,最后导致toBean方法失败。

可以看到DateMorpher类有这个构造函数可以传入Date defaultValue,在morph方法的第34行如果之前的转换均失败即返回defaultValue。但使用(Date)null作为defaultValue,在初始化DateMorpher对象时会报空指针异常,原因是DateMorpher类中有如下方法:

   public void setDefaultValue(Date defaultValue)
{
this.defaultValue = ((Date)defaultValue.clone());
} public Date getDefaultValue()
{
return (Date)this.defaultValue.clone();
}

“this.defaultValue.clone();”中defaultValue 为null所以报异常。

解决方法:

重新实现DateMorpher方法,修改setDefaultValue(Date defaultValue)和getDefaultValue()方法,对null进行处理

(当然也可是修改net.sf.ezmorph.object.DateMorpher方法,重新打包ezmorph-1.0.6.jar)。

以下是重新实现的DateMorpherEx方法:

 import net.sf.ezmorph.object.AbstractObjectMorpher;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import net.sf.ezmorph.MorphException;
import org.apache.commons.lang.builder.EqualsBuilder;
import org.apache.commons.lang.builder.HashCodeBuilder; public class DateMorpherEx extends AbstractObjectMorpher { private Date defaultValue;
private String[] formats;
private boolean lenient;
private Locale locale; public DateMorpherEx(String[] formats)
{
this(formats, Locale.getDefault(), false);
} public DateMorpherEx(String[] formats, boolean lenient)
{
this(formats, Locale.getDefault(), lenient);
} public DateMorpherEx(String[] formats, Date defaultValue)
{
this(formats, defaultValue, Locale.getDefault(), false);
} public DateMorpherEx(String[] formats, Date defaultValue, Locale locale, boolean lenient)
{
super(true);
if ((formats == null) || (formats.length == 0)) {
throw new MorphException("invalid array of formats");
} this.formats = formats; if (locale == null)
this.locale = Locale.getDefault();
else {
this.locale = locale;
} this.lenient = lenient;
setDefaultValue(defaultValue);
} public DateMorpherEx(String[] formats, Locale locale)
{
this(formats, locale, false);
} public DateMorpherEx(String[] formats, Locale locale, boolean lenient)
{
if ((formats == null) || (formats.length == 0)) {
throw new MorphException("invalid array of formats");
} this.formats = formats; if (locale == null)
this.locale = Locale.getDefault();
else {
this.locale = locale;
} this.lenient = lenient;
} public boolean equals(Object obj)
{
if (this == obj) {
return true;
}
if (obj == null) {
return false;
} if (!(obj instanceof DateMorpherEx)) {
return false;
} DateMorpherEx other = (DateMorpherEx)obj;
EqualsBuilder builder = new EqualsBuilder();
builder.append(this.formats, other.formats);
builder.append(this.locale, other.locale);
builder.append(this.lenient, other.lenient);
if ((super.isUseDefault()) && (other.isUseDefault())) {
builder.append(getDefaultValue(), other.getDefaultValue());
return builder.isEquals();
}if ((!super.isUseDefault()) && (!other.isUseDefault())) {
return builder.isEquals();
}
return false;
} public Date getDefaultValue()
{
if(this.defaultValue!=null)
return (Date)this.defaultValue.clone();
else
return this.defaultValue;
} public int hashCode()
{
HashCodeBuilder builder = new HashCodeBuilder();
builder.append(this.formats);
builder.append(this.locale);
builder.append(this.lenient);
if (super.isUseDefault()) {
builder.append(getDefaultValue());
}
return builder.toHashCode();
} public Object morph(Object value)
{
if (value == null) {
return null;
} if (Date.class.isAssignableFrom(value.getClass())) {
return (Date)value;
} if (!supports(value.getClass())) {
throw new MorphException(value.getClass() + " is not supported");
} String strValue = (String)value;
SimpleDateFormat dateParser = null; for (int i = 0; i < this.formats.length; ++i) {
if (dateParser == null)
dateParser = new SimpleDateFormat(this.formats[i], this.locale);
else {
dateParser.applyPattern(this.formats[i]);
}
dateParser.setLenient(this.lenient);
try {
return dateParser.parse(strValue.toLowerCase());
}
catch (ParseException localParseException)
{
} } if (super.isUseDefault()) {
return this.defaultValue;
}
throw new MorphException("Unable to parse the date " + value);
} public Class morphsTo()
{
return Date.class;
} public void setDefaultValue(Date defaultValue)
{
if(defaultValue!=null)
this.defaultValue = ((Date)defaultValue.clone());
else
this.defaultValue = null;
} public boolean supports(Class clazz)
{
return String.class.isAssignableFrom(clazz);
}
}

修改原 JsonToBean 方法,调用DateMorpherEx:

 public static <T> T JsonToBean(Class<T> clazz, String JsonString) {
JSONUtils.getMorpherRegistry().registerMorpher(
new DateMorpherEx(new String[] { "yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd", "yyyy-MM-dd't'HH:mm:ss" }, (Date) null));//调用DateMorpherEx,defaultValue为null
JSONObject jsonObject = JSONObject.fromObject(JsonString);
T entity = (T) JSONObject.toBean(jsonObject, clazz);
return entity;
}

json-lib反序列化时(JSONObject.toBean),时间类型为空的处理的更多相关文章

  1. Mysql 建表时,日期时间类型选择

    mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示  D ...

  2. 使用net.sf.json包提供的JSONObject.toBean方法时,日期转化错误解决办法

    解决办法: 需要在toBean之前添加配置 String[] dateFormats = new String[] {"yyyy-MM-dd HH:mm:ss"}; JSONUti ...

  3. MySQL建表时,日期时间类型选择

    MySQL(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示  D ...

  4. 接口测试中,数据驱动时,参数各类型,空或None的处理

    天天说接口测试,天天说数据驱动,但网上的各种教程太烂,遇到实际情况就傻眼了. 来来来,我们看一个例子 假设,有下面这样一个接口,获取用户信息,可以带的参数如下: 用户名(uname) str(),非必 ...

  5. .Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程

    JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询 ...

  6. mysql的五种日期和时间类型【转载】

    [mysql的五种日期和时间类型] mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期 ...

  7. MySQL时间类型及获取、展示处理

    MySQL时间格式 mysql所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值 ...

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

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

  9. Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解

    Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全   Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...

随机推荐

  1. mysql大数据高并发处理

    一.数据库结构的设计 如果不能设计一个合理的数据库模型,不仅会增加客户端和服务器段程序的编程和维护的难度,而且将会影响系统实际运行的性能.所以,在一个系统开始实施之前,完备的数据库模型的设计是必须的. ...

  2. install xdebug on fedora

    Compiling There is a wizard available that provides you with the correct file to download, and which ...

  3. Android开发系列之SQLite

    上篇博客提到过SQLite,它是嵌入式数据库,由于其轻巧但功能强大,被广泛的用于嵌入式设备当中.后来在智能手机.平板流行之后,它作为文件型数据库,几乎成为了智能设备单机数据库的必选,可以随着安卓app ...

  4. Activity组件

    Activity 间书作者:阿敏其人 关于Activity博文上 间书作者:阿敏其人 关于Activity博文中 间书作者:阿敏其人 关于Activity博文下

  5. linux日志审计项目案例实战(生产环境日志审计项目解决方案)

    所谓日志审计,就是记录所有系统及相关用户行为的信息,并且可以自动分析.处理.展示(包括文本或者录像) 推荐方法:sudo配合syslog服务,进行日志审计(信息较少,效果不错) 1.安装sudo命令. ...

  6. hdu 4099 Revenge of Fibonacci Trie树与模拟数位加法

    Revenge of Fibonacci 题意:给定fibonacci数列的前100000项的前n位(n<=40);问你这是fibonacci数列第几项的前缀?如若不在前100000项范围内,输 ...

  7. 信号量 sem_undo设置

    一 为什么要使用信号量 为了防止出现因多个程序同时访问一个共享资源而引发的一系列问题,我们需要一种方法,它可以通过生成并使用令牌来授权,在任一时刻只能有一个执行线程访问 代码的临界区域.临界区域是指执 ...

  8. java学习:用反射构造bean

    先贴一些反射的基本知识:-------------------------------------------------------------------- 一.什么是反射:反射的概念是由Smit ...

  9. Extjs 更新数据集Ext.PagingToolbar的start参数重置的处理

    问题:当翻页后,比如当前是第二页,start参数此时是5(初始为0),当切换左侧分类时,我们期望的是从所选分类下明细记录的第一条开始显示,结果发现不是这样,依然是从新数据的第二页开始显示,就是说ext ...

  10. JS 操作URL(重要)

    我们可以用javascript获得其中的各个部分1, window.location.href全部URl字符串(在浏览器中就是完整的地址栏)本例返回值: http://www.x2y2.com:80/ ...