<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 9364字,需瀏覽 19分鐘

           ·

          2020-09-18 14:07

          點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

          優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

          ? 作者?|??zhouweixin?

          來源 |? urlify.cn/iEbiAz

          66套java從入門到精通實(shí)戰(zhàn)課程分享

          1 相關(guān)概念

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

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

          2 序列化的作用

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

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

          3. 用于遠(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 流程

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

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

          3. 調(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?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 分析

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

          2. 否則將打印


          3. [{"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é)齡, 如何操作呢?

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

            1. 創(chuàng)建AgeSerializer的構(gòu)造方法

            2. 重寫serialize函數(shù)

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

          9.2 示例代碼

          AgeSerializer.java

          public?class?AgeSerializer?extends?StdSerializer?{
          ????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 流程

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

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

          3. 調(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}}

          分析

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

          2. 從數(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}}

          分析

          1. 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?{
          ????@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
          }

          分析

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

          2. 常見的零值:

            1. int: 0

            2. bool: false,

            3. String: null

          12 注解JsonIgnoreProperties

          該注解為類注解, 配置忽略序列化和反序列化的字段名
          如下所示, 忽略字段name和age

          @JsonIgnoreProperties(value?=?{"name",?"age"})
          @JsonInclude(value?=?JsonInclude.Include.NON_DEFAULT)
          public?class?Student?{

          13 注解JsonIgnore

          該注解為屬性注解, 表示忽略當(dāng)前屬性, 如下所示, 表示忽略name字段

          @JsonIgnore
          private?String?name;





          粉絲福利:108本java從入門到大神精選電子書領(lǐng)取

          ???

          ?長(zhǎng)按上方鋒哥微信二維碼?2 秒
          備注「1234」即可獲取資料以及
          可以進(jìn)入java1234官方微信群



          感謝點(diǎn)贊支持下哈?

          瀏覽 49
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  国产探花视频在线 | 日本黄色视频WWW | 成人催情爱爱免费视频 | 日逼逼视频 | 国产一级婬乱片 |