日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

jackson驼峰转下划线注解_jackson序列化与反序列化的应用实践

發布時間:2025/3/15 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 jackson驼峰转下划线注解_jackson序列化与反序列化的应用实践 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

作者 | zhouweixin

來源 | urlify.cn/iEbiAz

66套java從入門到精通實戰課程分享

1 相關概念

  • 序列化: 把對象轉換為字節序列的過程稱為對象的序列化
  • 反序列化: 把字節序列恢復為對象的過程稱為對象的反序列化
  • 2 序列化的作用

  • 用于把內存中的對象狀態保存到一個文件中或者數據庫中
  • 用于網絡傳送對象
  • 用于遠程調用傳輸對象
  • 3 準備序列化對象

    準備了兩個類, 教師類和學生類, 其中一個學生只有一個教師
    這里省略了構造方法和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中心倉庫中選擇了2.11.2版本的jackson-databind

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

    5 序列化與格式化輸出

    5.1 流程

  • 首先需要有一個待序列化對象, 本例中的student對象
  • 創建一個對象映射器, jackson包下的ObjectMapper
  • 調用序列化函數, 本例中的writeValueAsString, 將對象轉為字符串, 便于展示
  • 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 結果

    [?{??"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 分析

  • 示例中調用了方法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 場景

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

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

    6.2 示例代碼

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

    6.3 示例結果

    [?{??"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格式設置

    當前bornTime的格式為unix時間戮, 可讀性非常差

    現修改為yyyy-MM-dd HH:mm:ss
    并設置時區為東八區

    示例代碼

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

    結果

    [?{??"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設置為中文

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

    示例代碼

    @JsonValuepublic?String?getOrdinal()?{????return?name;}

    示例結果

    [?{??"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設置為序號

    有些場景喜歡用0和1等序號設置男女, 即枚舉的序號: 0表示男, 1表示女

    此時需要修改Set的getOrdinal方法

  • 修改返回值類型為int
  • 調用父類的getOrdinal方法
  • 示例代碼

    @JsonValuepublic?int?getOrdinal()?{????return?super.ordinal();}

    示例結果

    [?{??"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 拍平嵌套類型

    場景

    如前面提到的結果所示, teacher的兩個屬性并不在student的第一層,
    有時可能會更深的層次, 使用起來不太友好

    如何用teacher_name和teacher_age兩個屬性代替teacher呢?

  • 在Student的teacher屬性上添加注解JsonUnwrapped, 意為不包裹
  • 在Teacher的屬性上利用注解JsonProperty重命名
  • 示例代碼

    Student.java

    @JsonUnwrappedprivate?Teacher?teacher;

    Teacher.java

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

    示例結果

    [?{??"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 場景

    假如需要將年齡調整為理論學齡, 即將年齡減去7, 得到理論學齡, 如何操作呢?

  • 創建自定義年齡序列化器AgeSerializer, 繼承StdSerializer<>
  • 創建AgeSerializer的構造方法
  • 重寫serialize函數
  • 利用注解修指定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 示例結果

    [?{??"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 流程

  • 首先需要有序列化好的數據, 可以是string, byte[], 文件二進制等
  • 創建一個對象映射器, jackson包下的ObjectMapper
  • 調用反序列化函數, 本例中的readValue, 將字符串轉為對象
  • 10.2 反序列化對象數據

    示例代碼

    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);}

    示例結果

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

    分析

  • 為了便于打印對象數據, 重寫了Student和Teacher的toString方法
  • 從數據中可以看出, age的結果是錯誤的, 原因在于之前自定義的序列化器將年齡減小了7, 10.4節將會通過自定義反序列化器來解決此問題
  • 10.3 反序列化對象數組數據

    示例代碼

    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);????}}

    示例結果

    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的第二個參數需要傳類型, 這里推薦用數組, 不推薦用List, 具體原因筆者目前也沒花時間去研究
  • 10.4 自定義反序列化器

    從10.2節及10.3的現象中可以看出來, 僅僅自定義的序列化器會導致序列化的過程是正常的, 反序列化的過程仍然是默認邏輯, 有時候會導致意想不到的結果

    遇到此場景, 可以考慮自定義反序列化器

  • 創建自定義反序列化器AgeDeserializer, 繼承StdDeserializer<>
  • 重寫deserialize方法
  • 在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;

    示例結果

    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

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

    其中, Include有7種參數, 功能對比如下

    參數功能備注Include.ALWAYS屬性總是序列化(需要有get方法)默認值Include.NON_DEFAULT屬性為默認值不序列化如: int:0, bool:falseInclude.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}

    分析

  • 當屬性為默認值, 即零值時, 不序列化
  • 常見的零值:
  • int: 0
  • bool: false,
  • String: null
  • 12 注解JsonIgnoreProperties

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

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

    13 注解JsonIgnore

    該注解為屬性注解, 表示忽略當前屬性, 如下所示, 表示忽略name字段

    @JsonIgnoreprivate?String?name;@JsonIgnoreprivate?String?name;

    總結

    以上是生活随笔為你收集整理的jackson驼峰转下划线注解_jackson序列化与反序列化的应用实践的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。