When developing springMVC to receive data and deserialize objects, I encountered the problem that the date format cannot be converted normally.
E.g:
public class Entity{
private Date date ;
//get set method omitted
}
Front-end json data format: {"date":"2016-11-11 10:52"}
Use @requestBody Entity entity method to receive data error.
Checked the official documentation (http://docs.spring.io/spring/docs/4.3.1.BUILD-SNAPSHOT/spring-framework-reference/htmlsingle/#rest-mapping-json-converter) and found the following text :
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
:
The general idea is that springmvc matches the type through HttpMessageConverter and converts it.
Then I took a look at the Message Converters used by springMVC .
It is found that springMVC is used for requests in json format
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";
}
After compiling, put it into the project.
Summary: When you encounter a problem, looking for official documents can help you quickly locate the problem. As for how to solve the problem, the benevolent sees the benevolent and the wise sees the wisdom.