需求:

在我们的项目里希望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. 【HeadFirst设计模式】7.适配器模式与外观模式

    今晚学习完第七章,顺便做一下知识备忘. 适配器模模式: 定义:将一个类的接口,转换成客户期望的另一个接口.适配器让原本接口不兼容的类可以合作无间. 对象适配器: 类适配器: 外观模式: 提供了一个统一 ...

  2. Linux – RedHat7 / CentOS 7 忘记root密码修改

    1.(a) 开机出现grub boot loader 开机选项菜单时,立即点击键盘任意鍵,boot loader 会暂停. (b) 按下’e’,编辑选项菜单(c) 移动上下鍵至linux16 核心命令 ...

  3. js模拟苹果菜单

    模拟苹果菜单的js代码是从网上看到的,用来做导航菜单还是蛮好看的.这里借鉴一下. 效果描述:当鼠标移动离哪个图片最近的时候,这个图片最大,鼠标离的图片越远,则图片越小: 原理:主要用到了三角形的勾股定 ...

  4. git 使用事项

    基本安装可查看 http://help.github.com 如果删除了本地的文件,要恢复相关文件,在github存在(别人增加的),则:git pull <远程主机名> <远程分支 ...

  5. CSS3 animation-fill-mode 属性

    现在专注于移动端开发项目,对于动画这个点是非常重要的,每当我遇到一个新的知识点,我就会和大家一起分享 animation-fill-mode :把物体动画地从一个地方移动到另一个地方,并让它停留在那里 ...

  6. php中的数组定义和使用

    <?php //这个是一个php关于数组的例子,简要的说明了数组的基本使用 //定义一个字符串数组 $fruit = array(\"apple\",\"orang ...

  7. laravel homestead

    laravel homestead真是个好东西啊,折腾了很长时间,终于ok啦. 安装成功之后,在-目录下有个homstead,进入执行vagrant up clzdeMBP:Homestead clz ...

  8. Linux启用MySQL的InnoDB引擎

    前几天公司的一个项目组的同事反应说公司内部的一台Linux服务器上的MySQL没有InnoDB这个引擎,我当时想应该不可能啊,MySQL默认应该 就已经安装了这个引擎的吧,于是上服务器去看了看,发现还 ...

  9. Node.js和MongoDB - MongoJS入门

    第一次尝试翻译外国牛人的博文,希望大家喜欢. 本文源码详见:https://github.com/njaulj/mongojs 一点都不夸大的说,近年来node.js和mongodb的确是大放异彩,在 ...

  10. Boost format

    浅尝boost之format 概述      std::string是个很不错的东东,但实际使用时基本在每个程序里都会遇到不愉快的事情:格式化字符串.我甚至由于这个原因在代码里引入平台有关的MFC,A ...