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的工具,他的介绍就 ...
随机推荐
- 如何在Linux下创建与解压zip, tar, tar.gz和tar.bz2文件
这么多年来,数据压缩对我们来说是非常有用的.无论是在邮件中发送的图片用的zip文件还是在服务器压缩数据文件,我们都可以让下载更容易或者有效的节约磁盘空间.某些压缩格式有时允许我们以60%的比率(甚至更 ...
- Newtonsoft.Json.dll解析json的dll文件使用
要解析的json //解析前 //解析前 {,,,,,,,,,,},,,,,,,,,,,},,,,,,,,,,,,,,,,},,,,,,,,,},,,,,,,,,,,,},,,,,,,,,,,},,, ...
- 51nod贪心算法入门-----独木舟问题
独木舟问题 n个人,已知每个人体重,独木舟承重固定,每只独木舟最多坐两个人,可以坐一个人或者两个人.显然要求总重量不超过独木舟承重,假设每个人体重也不超过独木舟承重,问最少需要几只独木舟? 分析:按照 ...
- 如何使用命令提示符进入mysql
如果mysql安装时的路径不是在C盘,应进入mysql的bin目录中,然后在命令提示符中输入“mysql -u USERNAME -pPASSWORD ” 如果如果mysql安装时的路径是在C盘,直接 ...
- ECshop网点程序优化-后台添加类目自动选择上次父类目并计算Sort Order
如果在ECshop后台批量添加过大量类目的人都能体会到是多么的不方便(这点还是要说一下ECshop的产品经理,细节上还是要多注意),每次添加都需要在几百个类目里面找到要添加的父类目也是一个麻烦事,比如 ...
- Python学习笔记—itertools模块
这篇是看wklken的<Python进阶-Itertools模块小结> 学习itertools模块的学习笔记 在看itertools中各函数的源代码时,刚开始还比较轻松,但后面看起来就比较 ...
- CoreGraphics之CGContext绘图
0 CGContextRef context = UIGraphicsGetCurrentContext(); 设置上下文 1 CGContextMoveToPoint 开始画线 2 CGCon ...
- 导航栏 & 状态栏覆盖
当 automaticallyAdjustsScrollViewInsets 为 YES 时,也是默认行为,表现就比较正常了,和 edgesForExtendedLayout = UIRectEdge ...
- 区域生长算法的一种C++实现
区域生长算法是一种图像分割方法,能够将图像中具有相同特征的连通区域分割出来,同时保证较好的边缘信息. 区域生长算法的优点是简单,容易实现:但空间和时间复杂度较高,对分割图像要求较高,否则容易形成孔洞和 ...
- Pair Project: Elevator Scheduler [电梯调度算法的实现和测试]:思考题——谢勤政11061197
第一题: 大楼里面的电梯一般分区域,或考虑思考题第四题的情况,运行楼层不一样的电梯属于不同的区域.然后在接口IRequest和IPassenger还有IElevator里面都加上int area这个属 ...