SpringBoot(SpringMVC)序列化和反序列化Json时默认使用的是Jackson(例如使用@RequestBody反序列化前端传递过来的Json字符串时),前端
当咱们前端使用Json字符串传递到后台时日期格式多是时间戳(即long类型的数字),也有多是日期字符串(如:"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss")等等。java
若是是时间戳或者是yyyy-MM-dd格式的日期,Jackson会自动识别而且转换成功,如果yyyy-MM-dd HH:mm:ss这种格式的日期字符串的话,Jackson没法自动转换成Date类型。web
这里有几种解决方案,以下:spring
咱们能够在须要被反序列化的日期属性上添加com.fasterxml.jackson.annotation.JsonFormat注解,以下:apache
这个注解对于Jackson序列化以及反序列化均起做用(即将日期对象序列化成Json时格式为以上指定的格式,将Json反序列化成日期时会按照以上指定的日期格式进行解析,若日期字符串的格式不知足以上指定的格式将会直接报错)json
方法一咱们只能指定一种日期的格式,可是咱们前端可能传递各类类型的日期格式,这个时候咱们须要自定义Json日期转换器,以下在日期类型的属性上添加com.fasterxml.jackson.databind.annotation.JsonDeserialize注解,以下:mvc
其中DateJacksonConverter类是咱们自定义的日期转换类,这时在反序列化时咱们能够转换多种格式的日期,DateJacksonConverter类定义以下:app
package com.flying.eurekaclient; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateUtils; import org.springframework.context.annotation.Bean; import org.springframework.stereotype.Component; import java.io.IOException; import java.text.ParseException; import java.util.Date; /** * 自定义Jackson反序列化日期类型时应用的类型转换器,通常用于@RequestBody接受参数时使用 */ public class DateJacksonConverter extends JsonDeserializer<Date> { private static String[] pattern = new String[]{"yyyy-MM-dd", "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm:ss.S", "yyyy.MM.dd", "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm:ss.S", "yyyy/MM/dd", "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm:ss.S"}; @Override public Date deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException { Date targetDate = null; String originDate = p.getText(); if (StringUtils.isNotEmpty(originDate)) { try { long longDate = Long.valueOf(originDate.trim()); targetDate = new Date(longDate); } catch (NumberFormatException e) { try { targetDate = DateUtils.parseDate(originDate, DateJacksonConverter.pattern); } catch (ParseException pe) { throw new IOException(String.format( "'%s' can not convert to type 'java.util.Date',just support timestamp(type of long) and following date format(%s)", originDate, StringUtils.join(pattern, ","))); } } } return targetDate; } @Override public Class<?> handledType() { return Date.class; } }
在该方法中handledType()方法能够不用重写。ide
以上两种方法都须要在实体类上添加注解,这种方式污染了实体类,而且要是类太多的话,添加注解是一个麻烦事,这时咱们能够配置全局的日期类型转换器,以下:spa
package com.flying.eurekaclient; import com.fasterxml.jackson.databind.ObjectMapper; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; @Configuration public class ConverterConfig { @Bean public DateJacksonConverter dateJacksonConverter() { return new DateJacksonConverter(); } @Bean public Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean( @Autowired DateJacksonConverter dateJacksonConverter) { Jackson2ObjectMapperFactoryBean jackson2ObjectMapperFactoryBean = new Jackson2ObjectMapperFactoryBean(); jackson2ObjectMapperFactoryBean.setDeserializers(dateJacksonConverter); return jackson2ObjectMapperFactoryBean; } @Bean public MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter( @Autowired ObjectMapper objectMapper) { MappingJackson2HttpMessageConverter mappingJackson2HttpMessageConverter = new MappingJackson2HttpMessageConverter(); mappingJackson2HttpMessageConverter.setObjectMapper(objectMapper); return mappingJackson2HttpMessageConverter; } }
采用这种方式咱们自定义的DateJacksonConverter必须重写handledType()方法。
本人推荐采用方式三,这样不用污染实体类。
如下附上方式三的xml文件配置(若没有使用SpringBoot的话):
Tips:
1.关于使用SpringMVC接受前端传递过来的QueryParameter数据(即后台使用@RequestParam接收)或者formdata数据(后台采用@RequestParam或者直接用对象接收),
若其中存在日期数据,则能够采用如下博客提到的方式进行日期类型的正确转换:
http://www.javashuo.com/article/p-nipzrhvq-x.html
2.关于Jackson的基本用法参考:http://www.javashuo.com/article/p-rsmavewr-v.html