首页 > 代码库 > 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 }
但如果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 }
可以看到,在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 }
“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 }
修改原 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 }