net.sf.json.JSONException: Error while setting property=createDate type class java.lang.String

来源:互联网 发布:广州数控车床编程入门 编辑:程序博客网 时间:2024/05/29 01:55

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;    }

阅读全文
1 0
原创粉丝点击