欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

jackson序列化和反序列化的應(yīng)用實(shí)踐指南

 更新時(shí)間:2020年09月14日 10:33:05   作者:zhouweixin  
這篇文章主要給大家介紹了關(guān)于jackson序列化和反序列化的應(yīng)用實(shí)踐指南,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

源碼地址:https://github.com/zhouweixin/serializable

1 相關(guān)概念

序列化: 把對(duì)象轉(zhuǎn)換為字節(jié)序列的過程稱為對(duì)象的序列化

反序列化: 把字節(jié)序列恢復(fù)為對(duì)象的過程稱為對(duì)象的反序列化

2 序列化的作用

用于把內(nèi)存中的對(duì)象狀態(tài)保存到一個(gè)文件中或者數(shù)據(jù)庫(kù)中

用于網(wǎng)絡(luò)傳送對(duì)象

用于遠(yuǎn)程調(diào)用傳輸對(duì)象

3 準(zhǔn)備序列化對(duì)象

準(zhǔn)備了兩個(gè)類, 教師類和學(xué)生類, 其中一個(gè)學(xué)生只有一個(gè)教師

這里省略了構(gòu)造方法和setter, getter方法

Teacher.java

public class Teacher {
 private String name;
 private Integer age;
}

Student.java

package org.zwx;

public class Student {
 private String name;
 private Integer age;
 private Sex sex;
 private String fatherName;
 private Date bornTime;
 private Teacher teacher;
}

Sex.java

public enum Sex {
 MALE("男"), FEMALE("女");

 private String name;
 
 Sex(String name) {
 this.name = name;
 }

 public String getName() {
 return name;
 }
}

4 引入jackson依賴

本示例是基于gradle的, 從maven中心倉(cāng)庫(kù)中選擇了2.11.2版本的jackson-databind

compile group: 'com.fasterxml.jackson.core', name: 'jackson-databind', version: '2.11.2'

5 序列化與格式化輸出

5.1 流程

首先需要有一個(gè)待序列化對(duì)象, 本例中的student對(duì)象

創(chuàng)建一個(gè)對(duì)象映射器, jackson包下的ObjectMapper

調(diào)用序列化函數(shù), 本例中的writeValueAsString, 將對(duì)象轉(zhuǎn)為字符串, 便于展示

5.2 代碼

public void testSerializable() throws IOException {
 Student student1 = new Student("小明", 18, Sex.MALE, "王富貴", new Date(), new Teacher("李老師", 40));
 Student student2 = new Student("小花", 16, Sex.FEMALE, "錢很多", new Date(), new Teacher("趙老師", 38));
 List<Student> students = new ArrayList<>();
 students.add(student1);
 students.add(student2);

 ObjectMapper mapper = new ObjectMapper();
 String s = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(students);
 System.out.println(s);
}

5.3 結(jié)果

[ {
 "name" : "小明",
 "age" : 18,
 "sex" : "MALE",
 "fatherName" : "王富貴",
 "bornTime" : 1599996926917,
 "teacher" : {
 "name" : "李老師",
 "age" : 40
 }
}, {
 "name" : "小花",
 "age" : 16,
 "sex" : "FEMALE",
 "fatherName" : "錢很多",
 "bornTime" : 1599996926917,
 "teacher" : {
 "name" : "趙老師",
 "age" : 38
 }
} ]

5.4 分析

示例中調(diào)用了方法writerWithDefaultPrettyPrinter, 美化了json的格式

否則將打印

[{"name":"小明","age":18,"sex":"MALE","fatherName":"王富貴","bornTime":1599997061097,"teacher":{"name":"李老師","age":40}},{"name":"小花","age":16,"sex":"FEMALE","fatherName":"錢很多","bornTime":1599997061097,"teacher":{"name":"趙老師","age":38}}]

6 自定義序列化的名字

6.1 場(chǎng)景

假如需要將序列化的json由駝峰命名修改為下劃線命名, 如fatherName修改為father_name

只需要在字段fatherName上用注解JsonProperty配置

6.2 示例代碼

@JsonProperty("father_name")
private String fatherName;
@JsonProperty("born_time")
private Date bornTime;

6.3 示例結(jié)果

[ {
  "name" : "小明",
  "age" : 18,
  "sex" : "MALE",
  "teacher" : {
    "name" : "李老師",
    "age" : 40
  },
  "father_name" : "王富貴",
  "born_time" : 1599997157609
}, {
  "name" : "小花",
  "age" : 16,
  "sex" : "FEMALE",
  "teacher" : {
    "name" : "趙老師",
    "age" : 38
  },
  "father_name" : "錢很多",
  "born_time" : 1599997157610
} ]

7 自定義輸出格式

7.1 bornTime格式設(shè)置

當(dāng)前bornTime的格式為unix時(shí)間戮, 可讀性非常差

現(xiàn)修改為yyyy-MM-dd HH:mm:ss

并設(shè)置時(shí)區(qū)為東八區(qū)

示例代碼

@JsonProperty("born_time")
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date bornTime;

結(jié)果

[ {
  "name" : "小明",
  "age" : 18,
  "sex" : "MALE",
  "teacher" : {
    "name" : "李老師",
    "age" : 40
  },
  "father_name" : "王富貴",
  "born_time" : "2020-09-13 19:50:47"
}, {
  "name" : "小花",
  "age" : 16,
  "sex" : "FEMALE",
  "teacher" : {
    "name" : "趙老師",
    "age" : 38
  },
  "father_name" : "錢很多",
  "born_time" : "2020-09-13 19:50:47"
} ]

7.2 sex設(shè)置為中文

只需要為Sex添加一個(gè)方法getOrdinal, 并添加注解JsonValue即可

示例代碼

@JsonValue
public String getOrdinal() {
 return name;
}

示例結(jié)果

[ {
  "name" : "小明",
  "age" : 18,
  "sex" : "男",
  "teacher" : {
    "name" : "李老師",
    "age" : 40
  },
  "father_name" : "王富貴",
  "born_time" : "2020-09-13 19:57:47"
}, {
  "name" : "小花",
  "age" : 16,
  "sex" : "女",
  "teacher" : {
    "name" : "趙老師",
    "age" : 38
  },
  "father_name" : "錢很多",
  "born_time" : "2020-09-13 19:57:47"
} ]

7.3 sex設(shè)置為序號(hào)

有些場(chǎng)景喜歡用0和1等序號(hào)設(shè)置男女, 即枚舉的序號(hào): 0表示男, 1表示女

此時(shí)需要修改Set的getOrdinal方法

  1. 修改返回值類型為int
  2. 調(diào)用父類的getOrdinal方法

示例代碼

@JsonValue
public int getOrdinal() {
 return super.ordinal();
}

示例結(jié)果

[ {
  "name" : "小明",
  "age" : 18,
  "sex" : 0,
  "teacher" : {
    "name" : "李老師",
    "age" : 40
  },
  "father_name" : "王富貴",
  "born_time" : "2020-09-13 20:01:44"
}, {
  "name" : "小花",
  "age" : 16,
  "sex" : 1,
  "teacher" : {
    "name" : "趙老師",
    "age" : 38
  },
  "father_name" : "錢很多",
  "born_time" : "2020-09-13 20:01:44"
} ]

8 拍平嵌套類型

場(chǎng)景

如前面提到的結(jié)果所示, teacher的兩個(gè)屬性并不在student的第一層,
有時(shí)可能會(huì)更深的層次, 使用起來不太友好

如何用teacher_name和teacher_age兩個(gè)屬性代替teacher呢?

  1. 在Student的teacher屬性上添加注解JsonUnwrapped, 意為不包裹
  2. 在Teacher的屬性上利用注解JsonProperty重命名

示例代碼

Student.java

@JsonUnwrapped
private Teacher teacher;

Teacher.java

@JsonProperty("teacher_name")
private String name;
@JsonProperty("teacher_age")
private Integer age;

示例結(jié)果

[ {
  "name" : "小明",
  "age" : 18,
  "sex" : 0,
  "teacher_name" : "李老師",
  "teacher_age" : 40,
  "father_name" : "王富貴",
  "born_time" : "2020-09-13 20:21:53"
}, {
  "name" : "小花",
  "age" : 16,
  "sex" : 1,
  "teacher_name" : "趙老師",
  "teacher_age" : 38,
  "father_name" : "錢很多",
  "born_time" : "2020-09-13 20:21:53"
} ]

9 自定義序列化器

9.1 場(chǎng)景

假如需要將年齡調(diào)整為理論學(xué)齡, 即將年齡減去7, 得到理論學(xué)齡, 如何操作呢?

創(chuàng)建自定義年齡序列化器AgeSerializer, 繼承StdSerializer<>

  1. 創(chuàng)建AgeSerializer的構(gòu)造方法
  2. 重寫serialize函數(shù)

利用注解修指定Student屬性age的序列化器AgeSerializer

9.2 示例代碼

AgeSerializer.java

public class AgeSerializer extends StdSerializer<Integer> {
 protected AgeSerializer() {
 super(Integer.class);
 }

 @Override
 public void serialize(Integer value, JsonGenerator gen, SerializerProvider provider) throws IOException {
 gen.writeNumber(value - 7);
 }
}

Student.java

@JsonSerialize(using = AgeSerializer.class)
private Integer age;

9.3 示例結(jié)果

[ {
  "name" : "小明",
  "age" : 11,
  "sex" : 0,
  "teacher_name" : "李老師",
  "teacher_age" : 40,
  "father_name" : "王富貴",
  "born_time" : "2020-09-13 20:31:59"
}, {
  "name" : "小花",
  "age" : 9,
  "sex" : 1,
  "teacher_name" : "趙老師",
  "teacher_age" : 38,
  "father_name" : "錢很多",
  "born_time" : "2020-09-13 20:31:59"
} ]

10 反序列化

10.1 流程

首先需要有序列化好的數(shù)據(jù), 可以是string, byte[], 文件二進(jìn)制等

創(chuàng)建一個(gè)對(duì)象映射器, jackson包下的ObjectMapper

調(diào)用反序列化函數(shù), 本例中的readValue, 將字符串轉(zhuǎn)為對(duì)象

10.2 反序列化對(duì)象數(shù)據(jù)

示例代碼

public void testDeserializable() throws JsonProcessingException {
 String s = "{\"name\":\"小明\",\"age\":11,\"sex\":0,\"teacher_name\":\"李老師\",\"teacher_age\":40,\"father_name\":\"王富貴\",\"born_time\":\"2020-09-13 20:46:10\"}";
 ObjectMapper mapper = new ObjectMapper();
 Student student = mapper.readValue(s, Student.class);
 System.out.println(student);
}

示例結(jié)果

Student{name='小明', age=11, sex=MALE, fatherName='王富貴', bornTime=Sun Sep 13 20:46:10 CST 2020, teacher=Teacher{name='李老師', age=40}}

分析

為了便于打印對(duì)象數(shù)據(jù), 重寫了Student和Teacher的toString方法

從數(shù)據(jù)中可以看出, age的結(jié)果是錯(cuò)誤的, 原因在于之前自定義的序列化器將年齡減小了7, 10.4節(jié)將會(huì)通過自定義反序列化器來解決此問題

10.3 反序列化對(duì)象數(shù)組數(shù)據(jù)

示例代碼

public void testDeserializableStudents() throws JsonProcessingException {
 String s = "[{\"name\":\"小明\",\"age\":11,\"sex\":0,\"teacher_name\":\"李老師\",\"teacher_age\":40,\"father_name\":\"王富貴\",\"born_time\":\"2020-09-13 20:51:31\"},{\"name\":\"小花\",\"age\":9,\"sex\":1,\"teacher_name\":\"趙老師\",\"teacher_age\":38,\"father_name\":\"錢很多\",\"born_time\":\"2020-09-13 20:51:31\"}]";
 ObjectMapper mapper = new ObjectMapper();
 Student[] students = mapper.readValue(s, Student[].class);
 for (Student student : students) {
 System.out.println(student);
 }
}

示例結(jié)果

Student{name='小明', age=11, sex=MALE, fatherName='王富貴', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='李老師', age=40}}
Student{name='小花', age=9, sex=FEMALE, fatherName='錢很多', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='趙老師', age=38}}

分析

readValue的第二個(gè)參數(shù)需要傳類型, 這里推薦用數(shù)組, 不推薦用List, 具體原因筆者目前也沒花時(shí)間去研究

10.4 自定義反序列化器

從10.2節(jié)及10.3的現(xiàn)象中可以看出來, 僅僅自定義的序列化器會(huì)導(dǎo)致序列化的過程是正常的, 反序列化的過程仍然是默認(rèn)邏輯, 有時(shí)候會(huì)導(dǎo)致意想不到的結(jié)果

遇到此場(chǎng)景, 可以考慮自定義反序列化器

  1. 創(chuàng)建自定義反序列化器AgeDeserializer, 繼承StdDeserializer<>
  2. 重寫deserialize方法
  3. 在Student的age屬性上添加注解JsonDeserialize, 并指定反序列化器AgeDeserializer

示例代碼

AgeDeserializer.java

public class AgeDeserializer extends JsonDeserializer<Integer> {
 @Override
 public Integer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
 return p.getIntValue() + 7;
 }
}

Student.java

@JsonSerialize(using = AgeSerializer.class)
@JsonDeserialize(using = AgeDeserializer.class)
private Integer age;

示例結(jié)果

Student{name='小明', age=18, sex=MALE, fatherName='王富貴', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='李老師', age=40}}
Student{name='小花', age=16, sex=FEMALE, fatherName='錢很多', bornTime=Sun Sep 13 20:51:31 CST 2020, teacher=Teacher{name='趙老師', age=38}}

11 注解JsonInclude

該注解使用在實(shí)體類上, 格式@JsonInclude(value = JsonInclude.Include.NON_DEFAULT)

其中, Include有7種參數(shù), 功能對(duì)比如下

參數(shù) 功能 備注
Include.ALWAYS 屬性總是序列化(需要有g(shù)et方法) 默認(rèn)值
Include.NON_DEFAULT 屬性為默認(rèn)值不序列化 如: int:0, bool:false
Include.NON_EMPTY 屬性為空("")或null不序列化
Include.NON_NULL 屬性為null不序列化
Include.CUSTOM
Include.USE_DEFAULTS
Include.NON_ABSENT

代碼示例

Student.java

@JsonInclude(value = JsonInclude.Include.NON_DEFAULT)
public class Student {
public void testNonDefault() throws IOException {
 Student student = new Student("", 0, null, null, null, null);
 ObjectMapper mapper = new ObjectMapper();
 String s = mapper.writeValueAsString(student);
 System.out.println(s);
}

示例輸出

{
  "name" : "",
  "age" : -7
}

分析

當(dāng)屬性為默認(rèn)值, 即零值時(shí), 不序列化

常見的零值:

  1. int: 0
  2. bool: false,
  3. String: null

12 注解Transient

13 注解JsonIgnore

總結(jié)

到此這篇關(guān)于jackson序列化和反序列化的應(yīng)用實(shí)踐指南的文章就介紹到這了,更多相關(guān)jackson序列化和反序列化內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java多線程編程中的線程死鎖的問題解決

    Java多線程編程中的線程死鎖的問題解決

    線程死鎖是多線程編程中的一個(gè)常見問題,它發(fā)生在多個(gè)線程互相等待對(duì)方釋放資源的情況下,導(dǎo)致程序無法繼續(xù)執(zhí)行,本文就來介紹一下Java多線程編程中的線程死鎖的問題解決,感興趣的可以了解一下
    2023-08-08
  • java如何根據(jù)用戶請(qǐng)求獲取ip地址并解析省市信息

    java如何根據(jù)用戶請(qǐng)求獲取ip地址并解析省市信息

    根據(jù)當(dāng)前用戶本地IP地址,查詢IP地址庫(kù),獲取IP所在的省市信息,目前有多種方式實(shí)現(xiàn)該功能,這篇文章主要給大家介紹了關(guān)于java如何根據(jù)用戶請(qǐng)求獲取ip地址并解析省市信息的相關(guān)資料,需要的朋友可以參考下
    2023-12-12
  • SpringSecurity整合JWT的使用示例

    SpringSecurity整合JWT的使用示例

    本文主要介紹了SpringSecurity整合JWT的使用示例,整合Spring?Security和JWT,可以使我們的應(yīng)用程序更加安全和高效,感興趣的可以了解一下
    2023-11-11
  • Java實(shí)現(xiàn)萬年歷效果

    Java實(shí)現(xiàn)萬年歷效果

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)萬年歷效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Java判斷object對(duì)象為空(包括null ,““)的方法

    Java判斷object對(duì)象為空(包括null ,““)的方法

    這篇文章主要介紹了Java判斷對(duì)象是否為空(包括null ,“”)的方法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-12-12
  • 淺談Java線程Thread.join方法解析

    淺談Java線程Thread.join方法解析

    本篇文章主要介紹了淺談Java線程Thread.join方法解析,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-01-01
  • mybatis-plus 判斷isnull or的操作

    mybatis-plus 判斷isnull or的操作

    這篇文章主要介紹了mybatis-plus 判斷isnull or的操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-02-02
  • Java生成N個(gè)不重復(fù)的隨機(jī)數(shù)的三種方法總結(jié)

    Java生成N個(gè)不重復(fù)的隨機(jī)數(shù)的三種方法總結(jié)

    這篇文章主要為大家詳細(xì)介紹了三種Java生成N個(gè)不重復(fù)的隨機(jī)數(shù)的方法,文中的示例代碼講解詳細(xì),具有一定的參考價(jià)值,有需要的可以了解下
    2023-10-10
  • springboot 使用yml配置文件自定義屬性的操作代碼

    springboot 使用yml配置文件自定義屬性的操作代碼

    在SpringBoot中yml/yaml文件可以自定義一些屬性,以供注入給自定義bean對(duì)象的屬性,主要通過空格和層次來實(shí)現(xiàn),類似于python代碼,本文通過實(shí)例代碼給大家介紹springboot 使用yml配置文件自定義屬性,感興趣的朋友跟隨小編一起看看吧
    2024-03-03
  • springboot項(xiàng)目使用SchedulingConfigurer實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)的案例代碼

    springboot項(xiàng)目使用SchedulingConfigurer實(shí)現(xiàn)多個(gè)定時(shí)任務(wù)的案例代碼

    這篇文章主要介紹了springboot項(xiàng)目使用SchedulingConfigurer實(shí)現(xiàn)多個(gè)定時(shí)任務(wù),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2023-01-01

最新評(píng)論