Spring boot2.x-第04讲:Jackson
- 1. 基本介绍
- 2. Jackson的使用
- 2.1 API返回值去除为NULL的字段
- 2.1.1 现象
- 2.1.2 解决方案
- 2.2 Date类型入参和返回json格式化
- 2.2.1 现象一
- 2.2.2 解决方案
- 2.2.3 现象二
- 2.2.4 解决方案
- 3. 参考资料
1. 基本介绍
- 序列化
将内存中的对象转换为字节序列,方便持久化到磁盘(文件或数据库)或者网络传输。 - 反序列化
将字节序列转换为内存中的对象。
Spring MVC框架默认使用Jackson处理json。
对于Controller类:
请求时,在方法的形参中使用@RequestBody注解时,默认使用Jackson反序列化为对象
;
响应时,在类上使用@RestController注解,在返回前使用Jackson将对象序列化为json
。
2. Jackson的使用
2.1 API返回值去除为NULL的字段
当Controller类方法上使用@ResponseBody注解时,对于值为null的属性根本没必要返回。针对前后端分离的工程,有效解决数据传输过程中的流量浪费
。当然可以举一反三,比如不返回空字符串的属性等。
2.1.1 现象
Controller测试类
package com.tong.hao.online.service.controller.test;
import com.tong.hao.online.api.model.test.DemoReq;
import com.tong.hao.online.api.model.test.DemoRes;
import com.tong.hao.online.api.service.test.ITestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName TestController
* @Author 友野浩二
* @Description 测试控制器
* @Version 1.0
*/
@Api(tags = {"测试控制器"})
@RestController
@Slf4j
@RequestMapping(value = "/test")
public class TestController implements ITestController {
@Override
@ApiOperation(value = "数据校验测试-POST")
@RequestMapping(method = RequestMethod.POST, value = VALID_POST)
public DemoRes demoValidOfPost(@RequestBody DemoReq demoReq) {
System.err.println("数据校验测试-POST");
DemoRes demoRes = new DemoRes();
demoRes.setPhone("15789098766");
// demoRes.setAddress("陕西省汉中市汉台区石门栈道");
return demoRes;
}
}
可以看到响应模型没有设置address属性。现在进行测试如下:
请求报文
{
"tongInHead":{
"clientNo":"123",
"reqSystemId":"TWX",
"reqBusinessNo":"123456789",
"reqTranDate":"2019-09-28",
"reqControllerUrl":"/test/valid/post"
},
"name":"呵呵",
"age":"8",
"sex":"I"
}
响应报文
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:16:23.414"
},
"phone": "15789098766",
"address": null
}
问题
可以看到address的值为null,但还是给返回了。好像有点浪费流量。
2.1.2 解决方案
在application.ymal中配置spring.jackson.default-property-inclusion = 控制[序列化]期间包含的属性
。配置如下:
spring.jackson.default-property-inclusion=non_null
【注意】:该配置有可能不生效,此时需要查看项目中有没有使用@EnableWebMvc注解,如果使用了,就需要删除了;如果没使用再看一下有没有哪个类继承了WebMvcConfigurationSupport(包涵了@EnableWebMvc),如果有,则改为implements WebMvcConfigurer即可。
再次进行测试,响应报文如下:
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:28:20.307"
},
"phone": "15789098766"
}
由此可以看出address已经不再返回了。
2.2 Date类型入参和返回json格式化
当使用@ResponseBody或@RequestBody时,Date类型对象反序列化和序列化时,需要格式化。
2.2.1 现象一
Controller测试类
package com.tong.hao.online.service.controller.test;
import com.tong.hao.common.utils.ThBusinessUtils;
import com.tong.hao.common.utils.ThDateUtils;
import com.tong.hao.online.api.model.test.DemoReq;
import com.tong.hao.online.api.model.test.DemoRes;
import com.tong.hao.online.api.service.test.ITestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName TestController
* @Author 友野浩二
* @Description 测试控制器
* @Version 1.0
*/
@Api(tags = {"测试控制器"})
@RestController
@Slf4j
@RequestMapping(value = "/test")
public class TestController implements ITestController {
@Override
@ApiOperation(value = "数据校验测试-POST")
@RequestMapping(method = RequestMethod.POST, value = VALID_POST)
public DemoRes demoValidOfPost(@RequestBody DemoReq demoReq) {
DemoRes demoRes = new DemoRes();
demoRes.setPhone("15789098766");
// demoRes.setAddress("陕西省汉中市汉台区石门栈道");
demoRes.setBirthday(ThDateUtils.convertStr2Date("1994-03-03 20:20:20", ThDateUtils.PATTERN_ISO_DATETIME));
}
}
请求报文不变
响应报文如下
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:36:13.831"
},
"phone": "15789098766",
"birthday": "1994-03-03T12:20:20.000+0000"
}
问题
可以看到,日期……乱了……
2.2.2 解决方案
在application.ymal添加如下配置spring.jackson.date-format = 配置日期[序列化]和[反序列化]格式
# 东八区时间
spring.jackson.time-zone=GMT+8
# 指定项目中所有日期类型返回的json格式
spring.jackson.date-format=yyyy-MM-dd HH:mm:ss
再次测试,响应报文如下:
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:44:09.127"
},
"phone": "15789098766",
"birthday": "1994-03-03 20:20:20"
}
2.2.3 现象二
Controller测试类
package com.tong.hao.online.service.controller.test;
import com.tong.hao.common.utils.ThBusinessUtils;
import com.tong.hao.common.utils.ThDateUtils;
import com.tong.hao.online.api.model.test.DemoReq;
import com.tong.hao.online.api.model.test.DemoRes;
import com.tong.hao.online.api.service.test.ITestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
/**
* @ClassName TestController
* @Author 友野浩二
* @Description 测试控制器
* @Version 1.0
*/
@Api(tags = {"测试控制器"})
@RestController
@Slf4j
@RequestMapping(value = "/test")
public class TestController implements ITestController {
@Override
@ApiOperation(value = "数据校验测试-POST")
@RequestMapping(method = RequestMethod.POST, value = VALID_POST)
public DemoRes demoValidOfPost(@RequestBody DemoReq demoReq) {
System.err.println("数据校验测试-POST");
DemoRes demoRes = new DemoRes();
demoRes.setPhone("15789098766");
// demoRes.setAddress("陕西省汉中市汉台区石门栈道");
demoRes.setBirthday(ThDateUtils.convertStr2Date("1994-03-03 20:20:20", ThDateUtils.PATTERN_ISO_DATETIME));
demoRes.setWeddingDay(ThDateUtils.convertStr2Date("2019-10-03", ThDateUtils.PATTERN_ISO_DATE));
return demoRes;
}
}
响应模型添加了weddingDay属性。
请求报文不变
响应报文如下
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:46:34.543"
},
"phone": "15789098766",
"birthday": "1994-03-03 20:20:20",
"weddingDay": "2019-10-03 00:00:00"
}
问题
可以看到weddingDay属性在代码中赋值为"2019-10-03",即yyyy-MM-dd,并没有时分秒。
2.2.4 解决方案
针对响应模型中Date类型的属性需要特殊格式处理的,加入@JsonFormat注解即可。
package com.tong.hao.online.api.model.test;
import com.fasterxml.jackson.annotation.JsonFormat;
import com.tong.hao.common.entity.api.TongBaseResponse;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.util.Date;
@Setter
@Getter
@EqualsAndHashCode(callSuper = false)
@AllArgsConstructor
@NoArgsConstructor
public class DemoRes extends TongBaseResponse {
@ApiModelProperty(value = "手机号")
private String phone;
@ApiModelProperty(value = "住址")
private String address;
@ApiModelProperty(value = "破壳日")
private Date birthday;
@ApiModelProperty(value = "结婚纪念日")
@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd")
private Date weddingDay;
}
响应报文
{
"tongOutHead": {
"exceptionResultList": [
{
"retCode": "111111",
"retMsg": "交易成功!"
}
],
"timestamp": "2019-10-03 21:51:26.738"
},
"phone": "15789098766",
"birthday": "1994-03-03 20:20:20",
"weddingDay": "2019-10-03"
}
完成了……
3. 参考资料
- 3.Spring Boot 中Jackson配置,ObjectMapper使用详解
- Spring Boot jackson(Date类型入参、格式化,以及如何处理null)
感谢!!!