在开发springMVC接收数据,反序列化对象的时候,遇到了日期格式不能正常转化的问题。
例如:
public class Entity{
private Date date ;
//get set方法略
}
前端传的json数据格式:{"date":"2016-11-11 10:52"}
使用@requestBody Entity entity方式接收数据报错。
查了下官方文档(http://docs.spring.io/spring/docs/4.3.1.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#rest-mapping-json-converter),发现下面一段文字:
You convert the request body to the method argument by using an HttpMessageConverter
. HttpMessageConverter
is responsible for converting from the HTTP request message to an object and converting from an object to the HTTP response body. The RequestMappingHandlerAdapter
supports the @RequestBody
annotation with the following default HttpMessageConverters
:
大意是springmvc通过HttpMessageConverter对类型匹配,并转换。
紧接着去看了下,springMVC使用的Message Converters.
发现springMVC 对于json格式的请求使用
MappingJackson2XmlHttpMessageConverter做处理。
那么了解JACKson原理就能帮我们解决问题。
这里有一篇文章讲述了如何使用反序列化来处理格式问题。http://jackyrong.iteye.com/blog/2005323
使用这种方式,对于每种不同的格式化数据,都得去写一个处理类,并且还要注解,显得很麻烦。
于是我想到了第二种方式。
接收数据的时候,我使用string类型接收,然后使用阿里的fastjson去转换数据。
例如:
@RequestBody String myEntity
Entity entity = JSONObject.parseObject(myEntity,Entity.class);
@JSONField(format="yyyy-MM-dd HH:mm")
private Date date ; //格式化
但是再使用这种方式转换的时候,发现日期格式“2016-11-11 10:52”,也不能正确转换。
查了相关文档发现阿里支持的反序列化日期格式为:
- ISO-8601日期格式
- yyyy-MM-dd
- yyyy-MM-dd HH:mm:ss
- yyyy-MM-dd HH:mm:ss.SSS
- 毫秒数字
- 毫秒数字字符串
- .NET JSON日期格式
- new Date(1982932381111)
显然,这些不能满足我的需求。
于是在github(https://github.com/alibaba/fastjson/releases)上下载fastJson源码修改后编译:
找到com\alibaba\fastjson\util\TypeUtils.java对下面一段代码编辑:
if (value instanceof String) {
String strVal = (String) value;
JSONScanner dateLexer = new JSONScanner(strVal);
try {
if (dateLexer.scanISO8601DateIfMatch(false)) {
Calendar calendar = dateLexer.getCalendar();
return calendar.getTime();
}
} finally {
dateLexer.close();
}
if (strVal.startsWith("/Date(") && strVal.endsWith(")/")) {
String dotnetDateStr = strVal.substring(6, strVal.length() - 2);
strVal = dotnetDateStr;
}
if (strVal.indexOf('-') != -1) {
String format;
if (strVal.length() == JSON.DEFFAULT_DATE_FORMAT.length()) {
format = JSON.DEFFAULT_DATE_FORMAT;
} else if (strVal.length() == 10) {
format = "yyyy-MM-dd";
} else if (strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) {
format = "yyyy-MM-dd HH:mm:ss";
} else {
format = "yyyy-MM-dd HH:mm:ss.SSS";
}
SimpleDateFormat dateFormat = new SimpleDateFormat(format, JSON.defaultLocale);
dateFormat.setTimeZone(JSON.defaultTimeZone);
try {
return (Date) dateFormat.parse(strVal);
} catch (ParseException e) {
throw new JSONException("can not cast to Date, value : " + strVal);
}
}
if (strVal.length() == 0) {
return null;
}
longValue = Long.parseLong(strVal);
}
对这段代码进行扩展:
if (strVal.indexOf('-') != -1) {
String format;
if (strVal.length() == JSON.DEFFAULT_DATE_FORMAT.length()) {
format = JSON.DEFFAULT_DATE_FORMAT;
} else if (strVal.length() == 10) {
format = "yyyy-MM-dd";
} else if (strVal.length() == "yyyy-MM-dd HH:mm:ss".length()) {
format = "yyyy-MM-dd HH:mm:ss";
} else {
format = "yyyy-MM-dd HH:mm:ss.SSS";
}
编译后放入项目中,即可。
总结:遇到问题时候,查找官方文档,能帮助迅速定位问题,至于如何解决问题,仁者见仁智者见智。