springMVC requestBody获取json 反序列化,日期格式问题

在开发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 HttpMessageConverterHttpMessageConverter 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 @RequestBodyannotation 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"; 

                } 

 

编译后放入项目中,即可。

 

总结:遇到问题时候,查找官方文档,能帮助迅速定位问题,至于如何解决问题,仁者见仁智者见智。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值