SpringMVC @RequestBody Date類型的Json轉(zhuǎn)換方式
SpringMVC @RequestBody Date類型的Json轉(zhuǎn)換
正常使用Json或Gson對(duì)Date類型序列化成字符串時(shí),得到的是類似”Dec 5, 2017 8:03:34 PM”這種形式的字符串,前端得到了這種格式的很難明白這個(gè)具體是什么時(shí)間,可讀性很低。
同時(shí)如果用這種形式的字符串來反序列化為Date對(duì)象,也會(huì)失敗,這個(gè)過程是不可逆的。如何將Date對(duì)象序列化為指定格式的字符串,比如”yyyy-MM-dd”格式的字符串,以Gson的使用為例來說明。
對(duì)于Gson對(duì)象,可以使用GsonBuilder來實(shí)例化
通過GsonBuilder設(shè)置DateFormat的格式
Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
經(jīng)過這樣設(shè)置后,使用toJson(Object obj)方法對(duì)Date對(duì)象序列化時(shí),會(huì)輸出”yyyy-MM-dd HH:mm:ss”格式的字符串;
也可以將”yyyy-MM-dd HH:mm:ss”格式的字符串反序列化為一個(gè)Date對(duì)象。值得注意的是,當(dāng)一個(gè)Date對(duì)象未指定”HH:mm:ss”時(shí),會(huì)使用當(dāng)前時(shí)間來填充以補(bǔ)齊格式長度。
以上講的是Date對(duì)象的序列化和反序列化為字符串的方法,在SpingMVC框架中并不適用,下面講SpringMVC中Date的序列化和反序列化。
SpringMVC中,如果前端以GET的形式傳遞字符串,后端想將此字符串反序列化為Date對(duì)象,最常用的就是注冊(cè)Formatter對(duì)象
以零配置框架為例
public class String2DateFormatter implements Formatter<Date> {
private static final String DATE_TIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
private static final String DATE_FORMAT = "yyyy-MM-dd";
@Override
public String print(Date object, Locale locale) {
return new GsonBuilder().setDateFormat(DATE_TIME_FORMAT).create().toJson(object);
}
@Override
public Date parse(String text, Locale locale) throws ParseException {
if (text.length() > 10) {
return new SimpleDateFormat(DATE_TIME_FORMAT).parse(text);
} else {
return new SimpleDateFormat(DATE_FORMAT).parse(text);
}
}
}
public class MvcContextConfig extends WebMvcConfigurerAdapter {
......
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addFormatter(new String2DateFormatter());
}
......
}
當(dāng)然也可以用配置文件的形式配置,具體方法請(qǐng)百度。
當(dāng)前端傳遞字符串,Controller用Date類型的參數(shù)接受時(shí),會(huì)使用Formatter將字符串反序列化為Date對(duì)象。
如果前端以POST形式傳遞一個(gè)Json對(duì)象,對(duì)象內(nèi)部有一個(gè)Date屬性,前端傳遞的是字符串,后端用一個(gè)標(biāo)識(shí)@RequestBody的復(fù)合對(duì)象接收時(shí),F(xiàn)ormatter是不會(huì)起作用的。
此時(shí)起作用的是HttpMessageConverter的實(shí)現(xiàn)類。正常情況下項(xiàng)目?jī)?nèi)有Jackson或Gson依賴,能夠?qū)son反序列化為復(fù)合對(duì)象。
如果依賴了Jackson,且使用Jackson的HttpMessageConverter反序列化Json,那么僅支持反序列化簡(jiǎn)單數(shù)據(jù)類型的屬性,不支持Date類型;但是如果是Gson類型,是支持”yyyy-MM-dd HH:mm:ss”格式的反序列化的,確定不支持”yyyy-MM-dd”格式,其他格式不確定。
也就是說依賴Gson可以將前端的”yyyy-MM-dd HH:mm:ss”格式的字符串反序列化為Date對(duì)象,但是將Date對(duì)象返回給前端時(shí),解析得到的還是類似”Dec 5, 2017 8:03:34 PM”這種形式的字符串,并不可取。
當(dāng)我們使用Jackson作為Json對(duì)象的序列化和反序列化的解析器時(shí)
以零配置形式框架下的代碼實(shí)現(xiàn)為例講解
public class MvcContextConfig extends WebMvcConfigurerAdapter {
......
@Override
public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
StringHttpMessageConverter stringConverter = new StringHttpMessageConverter(Charset.forName("UTF-8"));
stringConverter.setWriteAcceptCharset(false);
converters.add(stringConverter);
converters.add(new ByteArrayHttpMessageConverter());
converters.add(new ResourceHttpMessageConverter());
converters.add(new MappingJackson2XmlHttpMessageConverter());
//設(shè)置Date類型使用HttpMessageConverter轉(zhuǎn)換后的格式,或者注冊(cè)一個(gè)GsonHttpMessageConverter,能直接支持字符串到日期的轉(zhuǎn)換
//當(dāng)指定了日期字符串格式后,如果傳的日志格式不符合,則會(huì)解析錯(cuò)誤
converters.add(new MappingJackson2HttpMessageConverter(
new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))));
//GsonHttpMessageConverter不支持yyyy-MM-dd形式的字符串轉(zhuǎn)換為日期
//converters.add(new GsonHttpMessageConverter());
}
......
}
當(dāng)我們選擇使用Jackson作為Json的解析器時(shí),需要注冊(cè)一個(gè)MappingJackson2HttpMessageConverter,對(duì)內(nèi)部默認(rèn)的objectMapper對(duì)象做一個(gè)拓展,需要指定日期格式化器,當(dāng)我們指定了具體的格式時(shí),只支持這種格式的轉(zhuǎn)換,其他的格式轉(zhuǎn)換時(shí)會(huì)報(bào)錯(cuò)。
因此需要前端在傳遞日期字符串時(shí),加上默認(rèn)的時(shí)間,比如”2017-12-2 00:00:00”,雖然多了點(diǎn)工作,但是能確保格式轉(zhuǎn)換的正確。
當(dāng)然并不是一定要”yyyy-MM-dd HH:mm:ss”,其他的格式也都支持的,比如”yyyy-MM-dd”等等,具體可以看項(xiàng)目需求自定義,前端傳遞日期字符串的格式需要符合自定義的格式。
當(dāng)配置了DateFormat時(shí),傳遞對(duì)象給前端,對(duì)象內(nèi)部有Date屬性,也會(huì)將其序列化為這個(gè)格式的字符串。
XML文件形式配置HttpMessageConverter的方法可自行百度。
@RequestBody接收json字符串,自動(dòng)將日期字符串轉(zhuǎn)換為java.util.Date
1.配置springMVC可以接收json字符串
<?xml version="1.0" encoding="UTF-8"?>
<beans
xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/context
http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/tx
http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/aop
http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/mvc
http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<!-- 解決@ResponseBody返回中文亂碼,解決@RequestBody接收J(rèn)son字符串自動(dòng)轉(zhuǎn)換為實(shí)體、List、Map格式轉(zhuǎn)換器 -->
<bean
class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
<property name="messageConverters">
<list>
<!--
<bean
class="org.springframework.http.converter.StringHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>text/html;charset=UTF-8</value>
</list>
</property>
</bean>
-->
<bean
class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter">
<property name="supportedMediaTypes">
<list>
<value>application/json;charset=UTF-8</value>
</list>
</property>
</bean>
</list>
</property>
</bean>
<!-- 掃描包,應(yīng)用Spring的注解 -->
<context:component-scan base-package="com.mvc.action"></context:component-scan>
<bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:viewClass="org.springframework.web.servlet.view.JstlView"
p:prefix="/"
p:suffix=".jsp">
</bean>
<!-- SpringMVC自定義攔截器,使SpringMVC開啟CORS支持 -->
<!--
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/*"/>
<bean class="com.mvc.dao.CorsInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
-->
<context:annotation-config/>
<mvc:annotation-driven/>
</beans>
2.@Controller類代碼
@RequestMapping(value="/addDicAppUsers.do")
@ResponseBody
public boolean addDicAppUsers(@RequestBody DicAppUsersModel dicAppUsersModel)
{
if(dicAppUsersService.addDicAppUsers(dicAppUsersModel))
{
return true;
}
else
{
return false;
}
}
3.實(shí)體類對(duì)象代碼
package com.mvc.model;
import java.util.Date;
import org.codehaus.jackson.map.annotate.JsonDeserialize;
import org.codehaus.jackson.map.annotate.JsonSerialize;
import com.mvc.imp.DateJsonDeserializer;
import com.mvc.imp.DateJsonSerializer;
/**
* 用戶視圖類
* @author suyunlong
*
*/
@SuppressWarnings("serial")
public class DicAppUsersModel implements java.io.Serializable
{
private long id;
private String loginid;
private String loginname;
private String loginpassword;
private String loginunitcode;
private String workplace;
@JsonSerialize(using=DateJsonSerializer.class)
@JsonDeserialize(using=DateJsonDeserializer.class)
private Date addtime;
private long sourceid;
@JsonSerialize(using=DateJsonSerializer.class)
@JsonDeserialize(using=DateJsonDeserializer.class)
private Date createdate;
public DicAppUsersModel() {
super();
}
public DicAppUsersModel(long id, String loginid, String loginname,
String loginpassword, String loginunitcode, String workplace,
Date addtime, long sourceid, Date createdate) {
super();
this.id = id;
this.loginid = loginid;
this.loginname = loginname;
this.loginpassword = loginpassword;
this.loginunitcode = loginunitcode;
this.workplace = workplace;
this.addtime = addtime;
this.sourceid = sourceid;
this.createdate = createdate;
}
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
public String getLoginid() {
return loginid;
}
public void setLoginid(String loginid) {
this.loginid = loginid;
}
public String getLoginname() {
return loginname;
}
public void setLoginname(String loginname) {
this.loginname = loginname;
}
public String getLoginpassword() {
return loginpassword;
}
public void setLoginpassword(String loginpassword) {
this.loginpassword = loginpassword;
}
public String getLoginunitcode() {
return loginunitcode;
}
public void setLoginunitcode(String loginunitcode) {
this.loginunitcode = loginunitcode;
}
public String getWorkplace() {
return workplace;
}
public void setWorkplace(String workplace) {
this.workplace = workplace;
}
public Date getAddtime() {
return addtime;
}
public void setAddtime(Date addtime) {
this.addtime = addtime;
}
public long getSourceid() {
return sourceid;
}
public void setSourceid(long sourceid) {
this.sourceid = sourceid;
}
public Date getCreatedate() {
return createdate;
}
public void setCreatedate(Date createdate) {
this.createdate = createdate;
}
}
4.DateJsonSerializer類代碼
package com.mvc.imp;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;
public class DateJsonSerializer extends JsonSerializer<Date>
{
public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public void serialize(Date date,JsonGenerator jsonGenerator,SerializerProvider serializerProvider)
throws IOException,JsonProcessingException
{
jsonGenerator.writeString(format.format(date));
}
}
5.DateJsonDeserializer類代碼
package com.mvc.imp;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.DeserializationContext;
import org.codehaus.jackson.map.JsonDeserializer;
public class DateJsonDeserializer extends JsonDeserializer<Date>
{
public static final SimpleDateFormat format=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
public Date deserialize(JsonParser jsonParser,DeserializationContext deserializationContext)
throws IOException,JsonProcessingException
{
try
{
return format.parse(jsonParser.getText());
}
catch(Exception e)
{
System.out.println(e.getMessage());
throw new RuntimeException(e);
}
}
}
這樣,就可以把接收到的json日期字符串轉(zhuǎn)換為Date了。后面,就可以直接通過Date類型保存日期數(shù)據(jù)了。
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
- html加css樣式實(shí)現(xiàn)js美食項(xiàng)目首頁示例代碼
- HTML+CSS+JavaScript做女朋友版的刮刮樂(一看就會(huì))
- JavaScript中html畫布的使用與頁面存儲(chǔ)技術(shù)詳解
- JS、CSS和HTML實(shí)現(xiàn)注冊(cè)頁面
- C#通過HttpWebRequest發(fā)送帶有JSON Body的POST請(qǐng)求實(shí)現(xiàn)
- 解決@RequestBody接收json對(duì)象報(bào)錯(cuò)415的問題
- 聊聊@RequestBody和Json之間的關(guān)系
- 在js中修改html body的樣式
相關(guān)文章
java實(shí)現(xiàn)微信公眾平臺(tái)自定義菜單的創(chuàng)建示例
這篇文章主要介紹了java實(shí)現(xiàn)微信公眾平臺(tái)自定義菜單的創(chuàng)建示例,需要的朋友可以參考下2014-04-04
Guava自動(dòng)加載緩存LoadingCache使用實(shí)戰(zhàn)詳解
這篇文章主要為大家介紹了Guava自動(dòng)加載緩存LoadingCache使用實(shí)戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12
Java關(guān)鍵字this(動(dòng)力節(jié)點(diǎn)Java學(xué)院整理)
java中的this隨處可見,用法也多。通常情況下理解this關(guān)鍵字還是很容易的,但是在我初學(xué)的時(shí)候,有一個(gè)疑問卻一直不能很清晰的理解,現(xiàn)在慢慢的理解了,下面通過本文給大家記錄下,有需要的朋友參考下2017-03-03
Java中的遞歸詳解(用遞歸實(shí)現(xiàn)99乘法表來講解)
這篇文章主要介紹了Java中的遞歸詳解(用遞歸實(shí)現(xiàn)99乘法表來講解),本文給出了普通的99乘法實(shí)現(xiàn)方法和用遞歸實(shí)現(xiàn)的方法,并對(duì)比它們的不同,體現(xiàn)出遞歸的運(yùn)用及理解,需要的朋友可以參考下2015-03-03
SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例
這篇文章主要介紹了SpringBoot使用Editor.md構(gòu)建Markdown富文本編輯器示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2018-03-03

