需求:

在我们的项目里希望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. windows 安装 setuptools

    在python的网站上 : https://pypi.python.org/pypi/setuptools/ 查找windows,显不如下: 点击 ez_setup.py进入, 并将内容复制下来, 保 ...

  2. Android - 安装 windows 7 安装 Android SDK 的时候出现的问题!(Connection to https://dl-ssl.google.com refused)

    Android - 安装 windows 7  安装 Android SDK 的时候出现的问题! 首先看到 Connection to https://dl-ssl.google.com refuse ...

  3. Unity帮助文档打开速度慢解决方法

    使用批量文本替换工具替换掉Unity安装目录中\Editor\Data\Documentation\en\Manual\下的所有文件中的如下两个部分:   1. <script type=&qu ...

  4. ECSHOP模板设置,前台英文后台中文,无需复制

    很多做英文站的朋友 只想让前台显示为英文,后台依就保持中文.这个要如何来做呢?网上也看到类似文章,好像还要进行目录复制与覆盖.我下面这个方法更简单,无需复制. 第一步: 通过后台设置实现前台英文.进入 ...

  5. 深入浅出分析C#接口的作用

    1.C#接口的作用 :C#接口是一个让很多初学C#者容易迷糊的东西,用起来好像很简单,定义接口,里面包含方法,但没有方法具体实现的代码,然后在继承该接口的类里面要实现接口的所有方法的代码,但没有真正认 ...

  6. JQ实现3D拖拽效果

    <!DOCTYPE HTML> <html onselectstart='return false'> <head> <meta http-equiv=&qu ...

  7. Excel技巧收录

    帮老婆弄Excel,自己也把学到的东西记录下,免得以后被问到又给忘了 数据透视,需先在数据透视区域加上表头,如公司名称.销量等,Excel数据透视默认将选择区域的第一行作为表头 VLOOKUP,VLO ...

  8. int([x[, base]]) : 将一个字符转换为int类型,base表示进制

    int([x[, base]]) : 将一个字符转换为int类型,base表示进制 >>> int(-12) -12 >>> int(-12.00) -12 > ...

  9. BZOJ 3990 [SDOI 2015] 排序 解题报告

    这个题哎呀...细节超级多... 首先,我猜了一个结论.如果有一种排序方案是可行的,假设这个方案是 $S$ . 那么我们把 $S$ 给任意重新排列之后,也必然可以构造出一组合法方案来. 于是我们就可以 ...

  10. [转载]MongoDB 常用命令

    mongodb由C++编写,其名字来自humongous这个单词的中间部分,从名字可见其野心所在就是海量数据的处理.关于它的一个最简洁描述为:scalable, high-performance, o ...