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 == 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        }
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 = ((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           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 }
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为null

5         JSONObject jsonObject = JSONObject.fromObject(JsonString);

6         T entity = (T) JSONObject.toBean(jsonObject, clazz);

7         return entity;

8     }
View Code

 

你可能感兴趣的:(JSONObject)