json-lib反序列化时(JSONObject.toBean),时间类型为空的处理
需求:
在我们的项目里希望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),时间类型为空的处理的更多相关文章
- Mysql 建表时,日期时间类型选择
mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示 D ...
- 使用net.sf.json包提供的JSONObject.toBean方法时,日期转化错误解决办法
解决办法: 需要在toBean之前添加配置 String[] dateFormats = new String[] {"yyyy-MM-dd HH:mm:ss"}; JSONUti ...
- MySQL建表时,日期时间类型选择
MySQL(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示 D ...
- 接口测试中,数据驱动时,参数各类型,空或None的处理
天天说接口测试,天天说数据驱动,但网上的各种教程太烂,遇到实际情况就傻眼了. 来来来,我们看一个例子 假设,有下面这样一个接口,获取用户信息,可以带的参数如下: 用户名(uname) str(),非必 ...
- .Net使用Newtonsoft.Json.dll(JSON.NET)对象序列化成json、反序列化json示例教程
JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询 ...
- mysql的五种日期和时间类型【转载】
[mysql的五种日期和时间类型] mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期 ...
- MySQL时间类型及获取、展示处理
MySQL时间格式 mysql所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值 ...
- Net中JSON序列化和反序列化处理(日期时间特殊处理)
0 缘由 笔者最近在web api端使用Json.Net进行序列化处理,而在调用端使用DataContractSerializer进行反序列化,遇到日期时间处理反序列化不成功[备注:笔者使用Net ...
- Newtonsoft.Json C# Json序列化和反序列化工具的使用、类型方法大全 C# 算法题系列(二) 各位相加、整数反转、回文数、罗马数字转整数 C# 算法题系列(一) 两数之和、无重复字符的最长子串 DateTime Tips c#发送邮件,可发送多个附件 MVC图片上传详解
Newtonsoft.Json C# Json序列化和反序列化工具的使用.类型方法大全 Newtonsoft.Json Newtonsoft.Json 是.Net平台操作Json的工具,他的介绍就 ...
随机推荐
- Web前端新人笔记之CSS结构和层叠
上一篇文章介绍了如何利用CSS选择器为元素应用各种丰富的样式,每个合法的文档都会生成一个结构树,了解这一点,就能根据元素的祖先.属性.兄弟等元素穿件选择器选择元素. 本篇文章将讨论3中机制之间的关系: ...
- lnmp 虚拟主机配置及重写
lnmp安装与调试,请看 http://www.cnblogs.com/lin3615/p/4376224.html 虚拟主机的配置编辑nginx配置文件 nginx.conf此为主配置文件 vim ...
- 多线程Demo
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...
- 解决ie8下h5元素兼容性的问题
HTML5的语义化标签以及属性,可以让开发者非常方便地实现清晰的web页面布局,加上CSS3的效果渲染,快速建立丰富灵活的web页面显得非常简单. HTML5的新标签元素有: <header&g ...
- 为什么要有binary-to-text encoding?
在wikipedia上看MIME的介绍的时候,有一节是关于Content-Transfer-Encoding的,里面提到了binary-to-text encoding,我就想,既然计算机中的信息使用 ...
- django1.6之mysql配置
# Database# https://docs.djangoproject.com/en/1.6/ref/settings/#databases setting 配置修改 INSTALLED_APP ...
- hdu 5646 DZY Loves Partition 二分+数学分析+递推
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5646 题意:将n分成k个正整数之和,要求k个数全部相同:并且这k个数的乘积最大为多少?结果mod 1e^9 ...
- C#基础|初探反射
什么是反射 我们编写的C#代码都可以编译成exe文件或dll文件.暂时先把他们叫做程序集吧,程序集中包含了很多信息.你写了一个类,类中会有字段,有属性,有方法,编译是会把这些信息保存在程序集中,暂时把 ...
- [转载]用c写PHP的扩展接口(php5,c++)
原文[http://bugs.tutorbuddy.com/php5cpp/php5cpp/] 第1节. 开始之前 开始前,我要说明:这篇文章所描述的主要是在UNIX的PHP环境上的. 另外一点我要说 ...
- 如何让Activiti-Explorer使用sql server数据库
从官网下载的Activiti-explorer的war文件内部默认是使用h2内存数据库的,如果想改用其他的数据库来做持久化,比如sql server,需要做如下配置. 1)修改db.propertie ...