Spring boot2.x-第04讲:Jackson

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. 参考资料

感谢!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值