接受入参的实体
@Data
public class UserVO {
/**
* 姓名
*/
private String userName;
/**
* 生日
*/
private Date birthday;
}
Controller方法
@PostMapping("/receiveUserVo")
public UserVO receiveUserVO(@RequestBody UserVO userVO){
System.out.println(userVO.getUserName());
System.out.println(userVO.getBirthday());
userVO.setBirthday(new Date());
return userVO;
}
调试一
-
采用postman测试接口,使用wireShark查看报文信息如下:可知日期解析失败。
POST /api/test/receiveUserVo HTTP/1.1 Content-Type: application/json User-Agent: PostmanRuntime/7.17.1 Accept: */* Cache-Control: no-cache Postman-Token: c1f02977-0435-4dbb-8db9-f2ac4c16cee0 Host: localhost:8888 Accept-Encoding: gzip, deflate Content-Length: 59 Cookie: JSESSIONID=41A840ADD2AA4F9186D82E4A177BF7A8 Connection: keep-alive { "userName" : "hk", "birthday" : "2018-02-12 23:23:23" }HTTP/1.1 400 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Sat, 12 Oct 2019 07:45:03 GMT Connection: close {"timestamp":1570866303815,"status":400,"error":"Bad Request","message":"JSON parse error: Cannot deserialize value of type `java.util.Date` from String \"2018-02-12 23:23:23\": not a valid representation (error: Failed to parse Date value '2018-02-12 23:23:23': Cannot parse date \"2018-02-12 23:23:23\": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null)); nested exception is com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type `java.util.Date` from String \"2018-02-12 23:23:23\": not a valid representation (error: Failed to parse Date value '2018-02-12 23:23:23': Cannot parse date \"2018-02-12 23:23:23\": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))\n at [Source: (PushbackInputStream); line: 3, column: 15] (through reference chain: cn.haoeasy.test.vo.UserVO[\"birthday\"])","path":"/api/test/receiveUserVo"}
解决方式
-
在日期类型上添加@JsonFormat(pattern = “yyyy-MM-dd HH:mm:ss”)
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss") private Date birthday;
-
备注
对于转换前端传过来的时间,
@JsonFormat
只适合 Content-Type 为application/json
的请求,如果是表单请求,请采用@DateTimeFormat
。
调试二
-
采用postman测试接口。报文信息如下:
POST /api/test/receiveUserVo HTTP/1.1 Content-Type: application/json User-Agent: PostmanRuntime/7.17.1 Accept: */* Cache-Control: no-cache Postman-Token: c8b02d59-f79f-4ae0-9692-b1d4194ae1a4 Host: localhost:8888 Accept-Encoding: gzip, deflate Content-Length: 59 Cookie: JSESSIONID=41A840ADD2AA4F9186D82E4A177BF7A8 Connection: keep-alive { "userName" : "hk", "birthday" : "2018-02-12 23:23:23" }HTTP/1.1 200 Content-Type: application/json;charset=UTF-8 Transfer-Encoding: chunked Date: Sat, 12 Oct 2019 07:51:37 GMT {"userName":"hk","birthday":"2018-02-12 23:23:23"}
-
控制台输出如下:
hk Tue Feb 13 07:23:23 CST 2018
-
问题
从postman测试返回的报文中我们可以看到,返回正常。
从控制台输出,我们可以看到,日期存在异常。日期异常的产生原因主要是:@JsonFormat 默认的时区是Greenwich Time, 默认的是格林威治时间,而我们是在东八区上,所以时间会比实际我们想得到的时间少八个小时。可以在@JsonFormat中带上时区,如下:
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss", timezone = "GMT+8") private Date birthday;
-
说明
@JsonFormat注解是一个时间格式化注解,比如我们存储在mysql中的数据是date类型的(前端也可以传入date类型格式),当我们读取出来封装在实体类中的时候,就会变成英文时间格式,而不是yyyy-MM-dd HH:mm:ss这样的中文时间,因此我们需要用到JsonFormat注解来格式化我们的时间。
当我们这样@ResponseBody输出json数据的时候,@JsonFormat注解标识的date属性就会自动返回yyyy-MM-dd HH:mm:ss样式的时间。
参考资料
[^1 ] @JsonFormat 实现原理