SpringMVC @RequestBody Date类型的Json转换方式

SpringMVC @RequestBody Date类型的Json转换

正常使用Json或Gson对Date类型序列化成字符串时,得到的是类似”Dec 5, 2017 8:03:34 PM”这种形式的字符串,前端得到了这种格式的很难明白这个具体是什么时间,可读性很低。

同时如果用这种形式的字符串来反序列化为Date对象,也会失败,这个过程是不可逆的。如何将Date对象序列化为指定格式的字符串,比如”yyyy-MM-dd”格式的字符串,以Gson的使用为例来说明。

对于Gson对象,可以使用GsonBuilder来实例化

通过GsonBuilder设置DateFormat的格式

Gson gson = new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();

经过这样设置后,使用toJson(Object obj)方法对Date对象序列化时,会输出”yyyy-MM-dd HH:mm:ss”格式的字符串;

也可以将”yyyy-MM-dd HH:mm:ss”格式的字符串反序列化为一个Date对象。值得注意的是,当一个Date对象未指定”HH:mm:ss”时,会使用当前时间来填充以补齐格式长度。

以上讲的是Date对象的序列化和反序列化为字符串的方法,在SpingMVC框架中并不适用,下面讲SpringMVC中Date的序列化和反序列化。

SpringMVC中,如果前端以GET的形式传递字符串,后端想将此字符串反序列化为Date对象,最常用的就是注册Formatter对象

以零配置框架为例

public class String2DateFormatter implements Formatter {
    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());
    }
    ......
}

当然也可以用配置文件的形式配置,具体方法请百度。

当前端传递字符串,Controller用Date类型的参数接受时,会使用Formatter将字符串反序列化为Date对象。

如果前端以POST形式传递一个Json对象,对象内部有一个Date属性,前端传递的是字符串,后端用一个标识@RequestBody的复合对象接收时,Formatter是不会起作用的。

此时起作用的是HttpMessageConverter的实现类。正常情况下项目内有Jackson或Gson依赖,能够将Json反序列化为复合对象。

如果依赖了Jackson,且使用Jackson的HttpMessageConverter反序列化Json,那么仅支持反序列化简单数据类型的属性,不支持Date类型;但是如果是Gson类型,是支持”yyyy-MM-dd HH:mm:ss”格式的反序列化的,确定不支持”yyyy-MM-dd”格式,其他格式不确定。

也就是说依赖Gson可以将前端的”yyyy-MM-dd HH:mm:ss”格式的字符串反序列化为Date对象,但是将Date对象返回给前端时,解析得到的还是类似”Dec 5, 2017 8:03:34 PM”这种形式的字符串,并不可取。

当我们使用Jackson作为Json对象的序列化和反序列化的解析器时

以零配置形式框架下的代码实现为例讲解

public class MvcContextConfig extends WebMvcConfigurerAdapter {
    ......
    @Override
    public void configureMessageConverters(List> 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());
        //设置Date类型使用HttpMessageConverter转换后的格式,或者注册一个GsonHttpMessageConverter,能直接支持字符串到日期的转换
        //当指定了日期字符串格式后,如果传的日志格式不符合,则会解析错误
        converters.add(new MappingJackson2HttpMessageConverter(
            new ObjectMapper().setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"))));
        //GsonHttpMessageConverter不支持yyyy-MM-dd形式的字符串转换为日期
        //converters.add(new GsonHttpMessageConverter());
    }
    ......
}

当我们选择使用Jackson作为Json的解析器时,需要注册一个MappingJackson2HttpMessageConverter,对内部默认的objectMapper对象做一个拓展,需要指定日期格式化器,当我们指定了具体的格式时,只支持这种格式的转换,其他的格式转换时会报错。

因此需要前端在传递日期字符串时,加上默认的时间,比如”2017-12-2 00:00:00”,虽然多了点工作,但是能确保格式转换的正确。

当然并不是一定要”yyyy-MM-dd HH:mm:ss”,其他的格式也都支持的,比如”yyyy-MM-dd”等等,具体可以看项目需求自定义,前端传递日期字符串的格式需要符合自定义的格式。

当配置了DateFormat时,传递对象给前端,对象内部有Date属性,也会将其序列化为这个格式的字符串。

XML文件形式配置HttpMessageConverter的方法可自行百度。

@RequestBody接收json字符串,自动将日期字符串转换为java.util.Date

1.配置springMVC可以接收json字符串



 
 
  
   
    
    
     
      
       application/json;charset=UTF-8
      
     
    
   
  
 
 
 
 
 
 
 
 
 

2.@Controller类代码

@RequestMapping(value="/addDicAppUsers.do")
 @ResponseBody
 public boolean addDicAppUsers(@RequestBody DicAppUsersModel dicAppUsersModel)
 {
  if(dicAppUsersService.addDicAppUsers(dicAppUsersModel))
  {
   return true;
  }
  else
  {
   return false;
  }
 }

3.实体类对象代码

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
{
 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
{
 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日期字符串转换为Date了。后面,就可以直接通过Date类型保存日期数据了。

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

你可能感兴趣的:(SpringMVC @RequestBody Date类型的Json转换方式)