博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
SpringBoot系列——Jackson序列化
阅读量:4618 次
发布时间:2019-06-09

本文共 10606 字,大约阅读时间需要 35 分钟。

  前言

  Spring Boot提供了与三个JSON映射库的集成:

  • Gson
  • Jackson
  • JSON-B

  Jackson是首选的默认库。

  官网介绍:

  

  

 

  通常,我们将Java对象转成Json时称之为序列化,反之将Json转成Java对象时称之为反序列化,本文简单介绍一下Jackson,以及在SpringBoot项目开发中常用的Jackson方法

 

  如何引入

  SpringBoot提供了JSON依赖,我们可以按下面方式引入

 

  1、直接引入JSON依赖

org.springframework.boot
spring-boot-starter-json

 

  2、一般情况下我们引入MVC,MVC里面帮我们引入了JSON依赖

org.springframework.boot
spring-boot-starter-web

  最终引入的依赖是

 

  Jackson注解

  Jackson的注解详细介绍

  英文官方介绍:

 

  常用注解

  @JsonProperty 序列化、反序列化时,属性的名称

  @JsonIgnoreProperties 序列化、反序列化忽略属性,多个时用“,”隔开

  @JsonIgnore  序列化、反序列化忽略属性

  @JsonAlias  为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用

  @JsonInclude 当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输

  @JsonFormat 序列化、反序列化时,格式化时间

 

  测试

  完整测试案例:

@Data//序列化、反序列化忽略的属性,多个时用“,”隔开@JsonIgnoreProperties({"captcha"})//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输@JsonInclude(JsonInclude.Include.NON_EMPTY)public class UserVo {    // 序列化、反序列化时,属性的名称    @JsonProperty("userName")    private String username;    // 为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用    @JsonAlias({"pass_word", "passWord"})    @JsonProperty("pwd")    private String password;    //序列化、反序列化时,格式化时间    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")    private Date createDate;    //序列化、反序列化忽略属性    @JsonIgnore    private String captcha;}

 

  写一个controller测试一下

  先写一个页面跳转

/**     * 跳转页面,页面引入了jquery,主要用于下面的ajax调用测试     */    @GetMapping("/")    public ModelAndView index(){        return new ModelAndView("index");    }

 

  使用@RestController标注类,相对于所有的方法都用@ResponseBody标注,MVC会帮我们调用序列化,将Java对象转成Json再响应给调用方,同时形参要加@RequestBody标注,MVC会帮我们调用反序列化将Json转成Java对象,这就要求我们调用的时候需要传一个Json字符串过来

@RestController@RequestMapping("/")public class TestContrller {
/* $.ajax({ type:"POST", url:"http://localhost:1099/testByJson", data:JSON.stringify({ userName:"sa", pass_word:"123fff", captcha:"abcd", createDate:"2019-08-05 11:34:31" }), dataType:"JSON", contentType:"application/json;charset=UTF-8", success:function(data){ console.log(data); }, error:function(data){ console.log("报错啦"); } }) */ @PostMapping("testByJson") public UserVo testByJson(@RequestBody UserVo userVo){ System.out.println(userVo); return userVo; }}

  

  调用测试

  1、先注释所有注解,仅打开这个两个类上面的注解@JsonIgnoreProperties、@JsonInclude

@Data//序列化、反序列化忽略的属性,多个时用“,”隔开@JsonIgnoreProperties({"captcha"})//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输@JsonInclude(JsonInclude.Include.NON_EMPTY)public class UserVo {    // 序列化、反序列化时,属性的名称//    @JsonProperty("userName")    private String username;    // 为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用//    @JsonAlias({"pass_word", "passWord"})//    @JsonProperty("pwd")    private String password;    //序列化、反序列化时,格式化时间//    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")    private Date createDate;    //序列化、反序列化忽略属性//    @JsonIgnore    private String captcha;}
UserVo

  前端调用时全部按属性名称

data:JSON.stringify({        username:"sa",        password:"123fff",        captcha:"abcd"    })

  反序列化(后端控制台打印)

UserVo(username=sa, password=123fff, createDate=null, captcha=null)

  序列化(ajax的回调)

{username: "sa", password: "123fff"}

  captcha属性前端已经传值,但设置了@JsonIgnoreProperties注解反序列化时该属性被忽略,因此为空,而序列化的时候@JsonInclude配置的是JsonInclude.Include.NON_EMPTY,当属性的值为空(null或者"")时,不进行序列化,所以序列化的最终结果如上所示

 

  2、先注释所有注解,放开@JsonProperty、@JsonAlias、@JsonIgnore

@Data//序列化、反序列化忽略的属性,多个时用“,”隔开//@JsonIgnoreProperties({"captcha"})//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输//@JsonInclude(JsonInclude.Include.NON_EMPTY)public class UserVo {    // 序列化、反序列化时,属性的名称    @JsonProperty("userName")    private String username;    // 为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用    @JsonAlias({"pass_word", "passWord"})    @JsonProperty("pwd")    private String password;    //序列化、反序列化时,格式化时间//    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")    private Date createDate;    //序列化、反序列化忽略属性    @JsonIgnore    private String captcha;}
UserVo

  前端调用还是按属性名称

data:JSON.stringify({        username:"sa",        password:"123fff",        captcha:"abcd"    })

  反序列化(后端控制台打印)

UserVo(username=null, password=null, createDate=null, captcha=null)

  序列化(ajax的回调)

{createDate: null, userName: null, pwd: null}

  captcha被@JsonIgnore标注,序列化、反序列忽略它,username、password被@JsonProperty标注,传参的时候只能用别名,password同时被@JsonAlias标注,可以用代替名称

  因此我们可以这样调用

data:JSON.stringify({        userName:"sa",        pass_word:"123fff",        //以下两种也一样        //passWord:"123fff",        //pwd:"123fff",        captcha:"abcd"    })

  反序列化(后端控制台打印)

UserVo(username=sa, password=123fff, createDate=null, captcha=null)

  序列化(ajax的回调)

{userName: "sa", pwd: "123fff"}

  

  3、先注释所有注解,放开@JsonFormat

@Data//序列化、反序列化忽略的属性,多个时用“,”隔开//@JsonIgnoreProperties({"captcha"})//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输//@JsonInclude(JsonInclude.Include.NON_EMPTY)public class UserVo {    // 序列化、反序列化时,属性的名称//    @JsonProperty("userName")    private String username;    // 为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用//    @JsonAlias({"pass_word", "passWord"})//    @JsonProperty("pwd")    private String password;    //序列化、反序列化时,格式化时间    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")    private Date createDate;    //序列化、反序列化忽略属性//    @JsonIgnore    private String captcha;}
UserVo

  前端调用

data:JSON.stringify({        createDate:"2019-08-05 11:34:31"    })

  反序列化(后端控制台打印)

UserVo(username=null, password=null, createDate=Mon Aug 05 11:34:31 GMT+08:00 2019, captcha=null)

  序列化(ajax的回调)

{username: null, password: null, createDate: "2019-08-05 11:34:31", captcha: null}

  PS:没有配置之前这样调用会报错400

Resolved [org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.Date` from String "2019-08-05 11:34:31": not a valid representation (error: Failed to parse Date value '2019-08-05 11:34:31': Cannot parse date "2019-08-05 11:34:31": 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 "2019-08-05 11:34:31": not a valid representation (error: Failed to parse Date value '2019-08-05 11:34:31': Cannot parse date "2019-08-05 11:34:31": while it seems to fit format 'yyyy-MM-dd'T'HH:mm:ss.SSSZ', parsing fails (leniency? null))

 

 

  如果不是以反序列化的方式注入,而是MVC的方式注入又是怎么样呢?去掉@RequestBody就变成MVC注入

/*        $.ajax({           type:"GET",           url:"http://localhost:1099/testByMvc",           data:{                username:"sa",                password:"123fff",                captcha:"abcd"            },           dataType:"JSON",           contentType:"application/json;charset=UTF-8",           success:function(data){               console.log(data);           },           error:function(data){                console.log("报错啦");           }        })     */    @GetMapping("testByMvc")    public UserVo testByMvc(UserVo userVo){        System.out.println(userVo);return userVo;    }

  放开所有注释

@Data//序列化、反序列化忽略的属性,多个时用“,”隔开@JsonIgnoreProperties({"captcha"})//当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输@JsonInclude(JsonInclude.Include.NON_EMPTY)public class UserVo {    // 序列化、反序列化时,属性的名称    @JsonProperty("userName")    private String username;    // 为反序列化期间要接受的属性定义一个或多个替代名称,可以与@JsonProperty一起使用    @JsonAlias({"pass_word", "passWord"})    @JsonProperty("pwd")    private String password;    //序列化、反序列化时,格式化时间    @JsonFormat(locale = "zh", timezone = "GMT+8", pattern = "yyyy-MM-dd HH:mm:ss")    private Date createDate;    //序列化、反序列化忽略属性    @JsonIgnore    private String captcha;}
UserVo

  MVC注入的时候,接参过程Jackson的注解就不再生效了,这时候我们传参就得按照MVC的规则来,Date类型首先就不能传字符串

  前端调用

data:{                username:"sa",                password:"123fff",                captcha:"abcd"            }

  后台打印

UserVo(username=sa, password=123fff, createDate=null, captcha=abcd)

  ajax回调,由于还是使用了@RestController,所有MVC会帮我们调用序列化再响应回去

{userName: "sa", pwd: "123fff"}

  那MVC方式注入,Date日期类型该怎么支持传字符串呢?在配置文件新增MVC日期格式化就可以愉快的传输固定格式的日期字符串了

#MVC接参时,日期处理spring.mvc.date-format=yyyy-MM-dd HH:mm:ss

  (偷个懒,效果与预期一样,就贴图了。。。)

 

  同时,不管是采用哪种注入方法,我们可以配置全局的日期处理,这样一来就可以愉快开发了

#全局日期格式化处理#MVC接参时,日期处理spring.mvc.date-format=yyyy-MM-dd HH:mm:ss#Jackson序列化、反序列化时,日期处理spring.jackson.date-format=yyyy-MM-dd HH:mm:ss

 

  我们顺便来看一下在配置文件都有哪些Jackson配置,每个配置的具体功能见名思意,就不阐述了

 

  ObjectMapper

  以上都是配置注解,具体操作都是MVC帮我们做了,那我们如何使用Jackson进行Json操作呢?我们在官方文档可以看到Jackson为我们提供了com.fasterxml.jackson.databind.ObjectMapper类操作Json

  官方文档相关介绍:

 

  常用方法

public static void main(String[] args) {        try {            ObjectMapper mapper = new ObjectMapper();            //当属性的值为空(null或者"")时,不进行序列化,可以减少数据传输            mapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);            //设置日期格式            mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));            //1、Java对象转Json字符串            UserVo userVo = new UserVo();            userVo.setUsername("张三");            userVo.setPassword("666");            String jsonString = mapper.writeValueAsString(userVo);            System.out.println(jsonString);            //2、Json字符串转Java对象            jsonString = "{\"userName\":\"张三\"}";            UserVo userVo1 = mapper.readValue(jsonString, UserVo.class);            System.out.println(userVo1);            //3、Java对象类型转换            HashMap
map = new HashMap<>(); map.put("userName", "张三"); UserVo userVo2 = mapper.convertValue(map, UserVo.class); System.out.println(userVo2); //4、将json字符串转换成List String listJsonString = "[{\"userName\":\"张三\"},{\"userName\":\"李四\"}]"; List
userVoList = mapper.readValue(listJsonString, mapper.getTypeFactory().constructParametricType(List.class, UserVo.class)); System.out.println(userVoList); } catch (IOException e) { e.printStackTrace(); } }

 

   还有一些不怎么常用的方法,比如下面这几个(除了转成Json字符串)

 

  后记

  通常,实体类用于ORM映射框架与数据打交道,比如:User,要求对象的属性要与数据库字段一一对应,少了不行,多了也不行,没有对应映射的得用注解标注(比如JPA),所以我们一般用Vo对象进行传输、接参等,会多很多乱七八糟的属性(分页信息,仅用于接参的临时属性等),比如:UserVo,User、UserVo两个对象使用工具类相互转换,有时候Vo对象有些乱七八糟的属性不想进行序列化传输,就需要设置序列化过滤

  在SpringBoot中使用Jackson操作Json序列化、反序列化的简单操作就暂时记录到这,以后再继续补充

 

  代码开源

  代码已经开源、托管到我的GitHub、码云:

  GitHub:

  码云:

转载于:https://www.cnblogs.com/huanzi-qch/p/11301453.html

你可能感兴趣的文章
本地存储 [记录]
查看>>
原型模式
查看>>
C#的一些必备技术
查看>>
【转载】学习顺序:顶级会议 ----> 顶级期刊 ------> 基础教材(博客) / 论文复现...
查看>>
Deep Learnning
查看>>
Css预处理器---Less(二)
查看>>
config windows virtual machine on mac
查看>>
Shell——windows上写完放入linux的时候需要注意的问题
查看>>
Activity总结
查看>>
naze32 rev6 swd 调试接口的引脚定义
查看>>
python3+requests接口自动化session操作
查看>>
qrsub sge
查看>>
thinkphp中array_diff运行无效 Invalid opcode 153/1/8
查看>>
Ubuntu彻底删除/卸载mysql,php,apache
查看>>
noj算法 装载问题 回溯法
查看>>
POJ 2429 GCD & LCM Inverse ★(pollard-ρ && DFS枚举)
查看>>
通过拦截器Interceptor实现Spring MVC中Controller接口访问信息的记录
查看>>
LeetCode: Minimum Depth of Binary Tree
查看>>
idea 部分按钮中的功能
查看>>
AngularJS的学习--TodoMVC的分析
查看>>