json-lib反序列化时(JSONObject.toBean),时间类型为空的处理

需求:

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

解决过程:

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

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

但如果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方法的源码,关于字符串转时间的代码如下:

 1       public Object morph(Object value)
 2        {
 3          if (value == null) {
 4            return null;
 5          }
 6
 7          if (Date.class.isAssignableFrom(value.getClass())) {
 8            return (Date)value;
 9          }
10
11          if (!supports(value.getClass())) {
12            throw new MorphException(value.getClass() + " is not supported");
13          }
14
15          String strValue = (String)value;
16          SimpleDateFormat dateParser = null;
17
18          for (int i = 0; i < this.formats.length; ++i) {
19            if (dateParser == null)
20              dateParser = new SimpleDateFormat(this.formats[i], this.locale);
21            else {
22              dateParser.applyPattern(this.formats[i]);
23            }
24            dateParser.setLenient(this.lenient);
25            try {
26              return dateParser.parse(strValue.toLowerCase());
27            }
28            catch (ParseException localParseException)
29            {
30            }
31          }
32
33          if (super.isUseDefault()) {
34            return this.defaultValue;
35          }
36          throw new MorphException("Unable to parse the date " + value);
37        }

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

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

1   public void setDefaultValue(Date defaultValue)
2       {
3           this.defaultValue = ((Date)defaultValue.clone());
4       }
5
6       public Date getDefaultValue()
7       {
8           return (Date)this.defaultValue.clone();
9       }

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

解决方法:

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

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

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

  1 import net.sf.ezmorph.object.AbstractObjectMorpher;
  2 import java.text.DateFormat;
  3 import java.text.ParseException;
  4 import java.text.SimpleDateFormat;
  5 import java.util.Date;
  6 import java.util.Locale;
  7 import net.sf.ezmorph.MorphException;
  8 import org.apache.commons.lang.builder.EqualsBuilder;
  9 import org.apache.commons.lang.builder.HashCodeBuilder;
 10
 11 public class DateMorpherEx extends AbstractObjectMorpher {
 12
 13     private Date defaultValue;
 14       private String[] formats;
 15       private boolean lenient;
 16       private Locale locale;
 17
 18       public DateMorpherEx(String[] formats)
 19       {
 20         this(formats, Locale.getDefault(), false);
 21       }
 22
 23       public DateMorpherEx(String[] formats, boolean lenient)
 24       {
 25         this(formats, Locale.getDefault(), lenient);
 26       }
 27
 28       public DateMorpherEx(String[] formats, Date defaultValue)
 29       {
 30         this(formats, defaultValue, Locale.getDefault(), false);
 31       }
 32
 33       public DateMorpherEx(String[] formats, Date defaultValue, Locale locale, boolean lenient)
 34       {
 35         super(true);
 36         if ((formats == null) || (formats.length == 0)) {
 37           throw new MorphException("invalid array of formats");
 38         }
 39
 40         this.formats = formats;
 41
 42         if (locale == null)
 43           this.locale = Locale.getDefault();
 44         else {
 45           this.locale = locale;
 46         }
 47
 48         this.lenient = lenient;
 49         setDefaultValue(defaultValue);
 50       }
 51
 52       public DateMorpherEx(String[] formats, Locale locale)
 53       {
 54         this(formats, locale, false);
 55       }
 56
 57       public DateMorpherEx(String[] formats, Locale locale, boolean lenient)
 58       {
 59         if ((formats == null) || (formats.length == 0)) {
 60           throw new MorphException("invalid array of formats");
 61         }
 62
 63         this.formats = formats;
 64
 65         if (locale == null)
 66           this.locale = Locale.getDefault();
 67         else {
 68           this.locale = locale;
 69         }
 70
 71         this.lenient = lenient;
 72       }
 73
 74       public boolean equals(Object obj)
 75       {
 76         if (this == obj) {
 77           return true;
 78         }
 79         if (obj == null) {
 80           return false;
 81         }
 82
 83         if (!(obj instanceof DateMorpherEx)) {
 84           return false;
 85         }
 86
 87         DateMorpherEx other = (DateMorpherEx)obj;
 88         EqualsBuilder builder = new EqualsBuilder();
 89         builder.append(this.formats, other.formats);
 90         builder.append(this.locale, other.locale);
 91         builder.append(this.lenient, other.lenient);
 92         if ((super.isUseDefault()) && (other.isUseDefault())) {
 93           builder.append(getDefaultValue(), other.getDefaultValue());
 94           return builder.isEquals();
 95         }if ((!super.isUseDefault()) && (!other.isUseDefault())) {
 96           return builder.isEquals();
 97         }
 98         return false;
 99       }
100
101       public Date getDefaultValue()
102       {
103           if(this.defaultValue!=null)
104               return (Date)this.defaultValue.clone();
105           else
106               return this.defaultValue;
107       }
108
109       public int hashCode()
110       {
111         HashCodeBuilder builder = new HashCodeBuilder();
112         builder.append(this.formats);
113         builder.append(this.locale);
114         builder.append(this.lenient);
115         if (super.isUseDefault()) {
116           builder.append(getDefaultValue());
117         }
118         return builder.toHashCode();
119       }
120
121       public Object morph(Object value)
122       {
123         if (value == null) {
124           return null;
125         }
126
127         if (Date.class.isAssignableFrom(value.getClass())) {
128           return (Date)value;
129         }
130
131         if (!supports(value.getClass())) {
132           throw new MorphException(value.getClass() + " is not supported");
133         }
134
135         String strValue = (String)value;
136         SimpleDateFormat dateParser = null;
137
138         for (int i = 0; i < this.formats.length; ++i) {
139           if (dateParser == null)
140             dateParser = new SimpleDateFormat(this.formats[i], this.locale);
141           else {
142             dateParser.applyPattern(this.formats[i]);
143           }
144           dateParser.setLenient(this.lenient);
145           try {
146             return dateParser.parse(strValue.toLowerCase());
147           }
148           catch (ParseException localParseException)
149           {
150           }
151
152         }
153
154         if (super.isUseDefault()) {
155           return this.defaultValue;
156         }
157         throw new MorphException("Unable to parse the date " + value);
158       }
159
160       public Class morphsTo()
161       {
162         return Date.class;
163       }
164
165       public void setDefaultValue(Date defaultValue)
166       {
167           if(defaultValue!=null)
168               this.defaultValue = ((Date)defaultValue.clone());
169           else
170               this.defaultValue = null;
171       }
172
173       public boolean supports(Class clazz)
174       {
175         return String.class.isAssignableFrom(clazz);
176       }
177 }

修改原 JsonToBean 方法,调用DateMorpherEx:

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

json-lib反序列化时(JSONObject.toBean),时间类型为空的处理

时间: 2024-08-30 02:12:47

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

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

mysql(5.5)所支持的日期时间类型有:DATETIME. TIMESTAMP.DATE.TIME.YEAR. 几种类型比较如下: 日期时间类型 占用空间 日期格式 最小值 最大值 零值表示  DATETIME  8 bytes  YYYY-MM-DD HH:MM:SS  1000-01-01 00:00:00 9999-12-31 23:59:59 0000-00-00 00:00:00  TIMESTAMP  4 bytes  YYYY-MM-DD HH:MM:SS  197001010

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

解决办法: 需要在toBean之前添加配置 String[] dateFormats = new String[] {"yyyy-MM-dd HH:mm:ss"}; JSONUtils.getMorpherRegistry().registerMorpher(new DateMorpher(dateFormats)); Map<String, Class> classMap = new HashMap<String, Class>(); MemberPlayLo

第九节:反序列化时重写程序集和类型

序列化对象时,格式化器输入类型及其定义程序集的全名.反序列化一个对象时,格式化器根据这个信息类准确的判断要为对象构造并初始化什么类型.前面,我们讨论了如何利用IserializationSurrogate接口接管一个特定的类型的序列化和反序列化.实现了IserializationSurrogate接口的类型与一个特定程序集中的特定类型关联在一起. 但在某些时候,IserializationSurrogate机制的灵活性显的差一些.在下面列举的情形中,有必要将一个类型反序列化成和序列化不同的一个类

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

天天说接口测试,天天说数据驱动,但网上的各种教程太烂,遇到实际情况就傻眼了. 来来来,我们看一个例子 假设,有下面这样一个接口,获取用户信息,可以带的参数如下: 用户名(uname) str(),非必填 用户ID(uid) int(), 非必填 用户电话 字典,非必填 所以接口用例就会有这种情况: 1.如果传的类型不对怎么办,比如uname,传的是整型 2.比如非必填的,传的是空或None,这两种都是不同的值 上面这2种情况在在数据驱动怎么处理?如果你的源数据是放在excel,就没法处理,所以要

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

JSON作为一种轻量级的数据交换格式,简单灵活,被很多系统用来数据交互,作为一名.NET开发人员,JSON.NET无疑是最好的序列化框架,支持XML和JSON序列化,高性能,免费开源,支持LINQ查询.目前已被微软集成于webapi框架之中,因此,熟练掌握JSON.NET相当重要,这篇文章是零度参考官网整理的示例,通过这些示例,可以全面了解JSON.NET提供的功能. Newtonsoft.Json的地址: 官网:http://json.codeplex.com/ 源码地址:https://gi

Json与Bean互转,Timestamp类型的问题

Json与Java Bean互相转换时,Bean中的Timestamp字段是无法直接处理的,需要实现两个转换器. DateJsonValueProcessor的作用是Bean转换为Json时将Timepstamp转换为指定的时间格式. 1 import java.text.DateFormat; 2 import java.text.SimpleDateFormat; 3 import java.util.Date; 4 import net.sf.json.JsonConfig; 5 impo

MySql 时间类型 &amp; JDBC时间类型

MySql时间类型:DATETIME & TIMESTAMP 长度 DATETIME类型包含DATE和TIME,范围1000-01-01 00:00:00 ~ 9999-12-31 23:59:59.DATETIME还能包含毫秒,例如2018-03-11 14::13:22.999 TIMESTAMP也能存储日期和时间,但是范围只有1970-01-01 00:00:01 UTC ~ 2038-01-19 03:14:07 UTC 时区 DATETIME存储的时间不包含时区 TIMESTAMP存储

DataContractJsonSerializer序列化时间类型时转换为UTC溢出问题

问题描述 如下一个实体类,含有非空时间类型属性,默认是C#的最小时间,在使用DataContractJsonSerializer将该类对象序列化成JSON时,抛出异常信息:System.Runtime.Serialization.SerializationException:"在转换为 UTC 时,大于 DateTime.MaxValue 或小于 DateTime.MinValue 的 DateTime 值无法序列化为 JSON.". 实体类 public class Post { p

数据库里面DataTime时间类型字段,如果为null时

tran.TransactionTime = bet.CreationDate.ToString() == "0001/1/1 0:00:00" ? DateTime.Now : bet.CreationDate; 数据库里面DataTime时间类型字段,如果为null时,查询出来时间值为"0001/1/1 0:00:00" 这是一个溢出SqlDateTime超出范围的时间值,将它再插入数据库时会报错的 数据库里面DataTime时间类型字段,如果为null时,布布