1. 程式人生 > >SpringMVC 返回Java8 時間JSON資料的格式化問題處理

SpringMVC 返回Java8 時間JSON資料的格式化問題處理

有時在Spring MVC中返回JSON格式的response的時候會使用@ResponseBody註解,不過在處理java8中時間的時候會很麻煩,一般我們使用的HTTPMessageConverter是MappingJackson2HttpMessageConverter,它預設返回的時間格式是這種:

 1 "startDate" : {
 2     "year" : 2010,
 3     "month" : "JANUARY",
 4     "dayOfMonth" : 1,
 5     "dayOfWeek" : "FRIDAY",
 6     "dayOfYear" : 1,
7 "monthValue" : 1, 8 "hour" : 2, 9 "minute" : 2, 10 "second" : 0, 11 "nano" : 0, 12 "chronology" : { 13 "id" : "ISO", 14 "calendarType" : "iso8601" 15 } 16 }

但是我們不會返回這種給前端使用,針對LocalDate想要返回的格式是2016-11-26,而LocalDateTime想要返回的格式是2016-11-26 21:04:34這樣的資料。通過專案研究並查閱相關資料,這裡介紹下個人研究中實現的兩種方式。

解決方法一:

若是maven專案,在pom中引入下面的jar包:

1 <dependency>
2      <groupId>com.fasterxml.jackson.datatype</groupId>
3      <artifactId>jackson-datatype-jsr310</artifactId>
4      <version>2.8.5</version>
5 </dependency>

然後在你想要JSON化的POJO欄位的get函式上加上一個@JsonSerializer註解,如下

 1 import com.fasterxml.jackson.annotation.JsonFormat;
 2 
 3 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
 4 public LocalDateTime getBirthday() {
 5         return this.loginTime;
 6     }
 7 
 8 @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
 9 public LocalDateTime getLastLoginTime() {
10         return this.loginTime;
11     }

這種方式的優點是可以針對具體域型別設定不同顯示方式,然而優點也是缺點,因為每個日期屬性都要手動新增,實際中日期屬性又是普遍必備,並且需要額外引入jsr310的jar包。

解決方法二:

繼承ObjectMapper來實現返回json字串。MappingJackson2HttpMessageConverter主要通過ObjectMapper來實現返回json字串。這裡我們編寫一個JsonUtil類,獲取ObjectMapper以針對java8中新的日期時間API,註冊相應的JsonSerializer<T>。

 1 /**
 2  * json處理工具類
 3  * 
 4  * 
 5  */
 6 @Component
 7 public class JsonUtil {
 8 
 9     private static final ObjectMapper mapper;
10 
11     public ObjectMapper getMapper() {
12         return mapper;
13     }
14 
15     static {
16 
17         mapper = new ObjectMapper();
18 
19         SimpleModule module = new SimpleModule();
20         module.addSerializer(LocalDate.class, new LocalDateSerializer());
21         module.addSerializer(LocalTime.class, new LocalTimeSerializer());
22         module.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
23         mapper.registerModule(module);
24     }
25 
26     public static String toJson(Object obj) {
27         try {
28             return mapper.writeValueAsString(obj);
29         } catch (Exception e) {
30             throw new RuntimeException("轉換json字元失敗!");
31         }
32     }
33 
34     public <T> T toObject(String json, Class<T> clazz) {
35         try {
36             return mapper.readValue(json, clazz);
37         } catch (IOException e) {
38             throw new RuntimeException("將json字元轉換為物件時失敗!");
39         }
40     }
41 }
42 
43 class LocalDateSerializer extends JsonSerializer<LocalDate> {
44 
45     private static final DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
46 
47     @Override
48     public void serialize(LocalDate value, JsonGenerator jgen, SerializerProvider provider)
49             throws IOException, JsonProcessingException {
50         jgen.writeString(dateFormatter.format(value));
51     }
52 }
53 
54 class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
55 
56     private static final DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
57 
58     @Override
59     public void serialize(LocalDateTime value, JsonGenerator jgen, SerializerProvider provider)
60             throws IOException, JsonProcessingException {
61         jgen.writeString(dateTimeFormatter.format(value));
62     }
63 
64 }
65 
66 class LocalTimeSerializer extends JsonSerializer<LocalTime> {
67 
68     private static final DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern("HH:mm:ss");
69 
70     @Override
71     public void serialize(LocalTime value, JsonGenerator jgen, SerializerProvider provider)
72             throws IOException, JsonProcessingException {
73         jgen.writeString(timeFormatter.format(value));
74 
75     }
76 
77 }
View Code

然後在springmvc的配置檔案中,再將<mvc:annotation-driven/>改為以下配置,配置一個新的json轉換器,將它的ObjectMapper物件設定為JsonUtil中的objectMapper物件,此轉換器比spring內建的json轉換器優先順序更高,所以與json有關的轉換,spring會優先使用它。

 1 <mvc:annotation-driven>
 2         <mvc:message-converters>
 3             <bean
 4                 class="org.springframework.http.converter.json.MappingJackson2HttpMessageConverter">
 5                 <property name="objectMapper" value="#{jsonUtil.mapper}" />
 6                 <property name="supportedMediaTypes">
 7                     <list>
 8                         <value>application/json;charset=UTF-8</value>
 9                     </list>
10                 </property>
11             </bean>
12         </mvc:message-converters>
13     </mvc:annotation-driven>
View Code

然後java8中的幾種日期和時間型別就可以正常友好的顯示了。優點是全域性統一管理日期和時間等型別,缺點對pojo中的某個域做特殊處理。