首页 > 代码库 > json-lib反序列化时(JSONObject.toBean),时间类型为空的处理

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     }
View Code

但如果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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/ (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        }
View Code

 

可以看到,在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 =http://www.mamicode.com/ ((Date)defaultValue.clone());4       }5 6       public Date getDefaultValue()7       {8           return (Date)this.defaultValue.clone();9       }
View Code

“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           else106               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 =http://www.mamicode.com/= 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 =http://www.mamicode.com/ (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 =http://www.mamicode.com/ ((Date)defaultValue.clone());169           else170               this.defaultValue = http://www.mamicode.com/null;171       }172 173       public boolean supports(Class clazz)174       {175         return String.class.isAssignableFrom(clazz);176       }177 }
View Code

修改原 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为null5         JSONObject jsonObject = JSONObject.fromObject(JsonString);6         T entity = (T) JSONObject.toBean(jsonObject, clazz);7         return entity;8     }
View Code