在項目中如何對Map List等對象序列化及反序列化

我們知道,在自定義類中,若想完成序列化必須要實現Serializable接口。

那么在實現后如何進行序列化呢?

一.普通對象

序列化:

1.首先我們要定義一個? 序列化所需要的工具類?ObjectMapper?

        //定義序列化所需要的工具類  轉化機器ObjectMapper objectMapper = new ObjectMapper();

2.定義所要序列化的類? (在這里以我正在做的項目中的一個類為例)

        //定義所要序列化的類   轉化原料CommonResult<String> result = CommonResult.error(500, "系統錯誤");

3.調用objectMapper.writeValueAsString()方法序列化為String

        //定義序列化后的類   轉化產品String str = null;//序列化try {str = objectMapper.writeValueAsString(result);} catch (JsonProcessingException e) {e.printStackTrace();}

這個方法只有一個參數,就是要序列化對象本身

打印結果

?反序列化:

        //反序列化   JsonParser:反序列化所轉化的對象   ResolvedType: 所返回的對象的類型try {CommonResult<String> commonResult1 = objectMapper.readValue(str, CommonResult.class);System.out.println(commonResult1);} catch (JsonProcessingException e) {e.printStackTrace();}

這個方法有兩個參數

JsonParser:反序列化所轉化的對象(str? 剛序列化后的產物)??

ResolvedType: 所返回的對象的類型(CommonResult)

返回值就是原本對象?

打印結果:

二.List對象

序列化:

1.定義ObjectMapper (上文已經定義過)

2.初始化所要序列化的List(用于演示)

3.調用objectMapper.writeValueAsString()可見與普通對象無差別

真正的區別在反序列化

        //序列化 ListList<CommonResult<String>> list = Arrays.asList(CommonResult.success("success1"),CommonResult.success("success2"));try {str = objectMapper.writeValueAsString(list);System.out.println(str);} catch (JsonProcessingException e) {e.printStackTrace();}

反序列化:

因為我們不能保證在每個List中存放的類型一致,所以在objectMapper.readValue()方法的第二個參數(類型)不能保持一致,這里引入一個新參數JavaType,也就是反序列化調用的方法參數

看名字就知道它是用于描述java中類型的,我們看看他怎么用的。

        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, CommonResult.class);

1.調用objectMapper的類型工廠objectMapper.getTypeFactory()(充當工具)

2.獲取JavaType??constructParametricType()

這個方法有多個重載,這里有兩個參數:

第一個不會變,要序列化的對象類型(List)

第二個:List中的屬性類型(CommonResult)

在Map中由于Map有兩個參數所以會有第三個參數(按順序寫即可)

然后調用objectMapper.readValue()即可

        List<CommonResult<String>> result2 = null;try {result2 = objectMapper.readValue(str, javaType);//        System.out.println(result2);for(CommonResult<String> a : result2) {System.out.println(a.getData());}} catch (JsonProcessingException e) {e.printStackTrace();}

三.Map對象

還是按照前文,注意constructParametricType()方法傳入三個參數即可

        //序列化 MapMap<Integer, CommonResult<String>> map = new HashMap<>();map.put(3,CommonResult.success("success3"));map.put(4,CommonResult.success("success4"));try {str = objectMapper.writeValueAsString(map);System.out.println(str);} catch (JsonProcessingException e) {e.printStackTrace();}//反序列化  先構造一個所需要的參數類型  Map類型  內部是什么類型JavaType javaType2 = objectMapper.getTypeFactory().constructParametricType(Map.class, Integer.class, CommonResult.class);Map<Integer, CommonResult<String>> result3 = null;try {result3 = objectMapper.readValue(str, javaType2);//        System.out.println(result2);System.out.println(map.get(3).getCode());} catch (JsonProcessingException e) {e.printStackTrace();}

四.封裝成方法

在上述寫過程中try了許多的異常,非常的冗余,我們可以參考一下JacksonJsonParser源碼對這個問題解決方法。

在源碼部分對List與Map是這樣實現的:

    public Map<String, Object> parseMap(String json) {return (Map)this.tryParse(() -> {return (Map)this.getObjectMapper().readValue(json, MAP_TYPE);}, Exception.class);}public List<Object> parseList(String json) {return (List)this.tryParse(() -> {return (List)this.getObjectMapper().readValue(json, LIST_TYPE);}, Exception.class);}

我們發現它并沒有進行異常捕獲,進入tryParse()方法看一下:

    protected final <T> T tryParse(Callable<T> parser, Class<? extends Exception> check) {try {return parser.call();} catch (Exception var4) {if (check.isAssignableFrom(var4.getClass())) {throw new JsonParseException(var4);} else {ReflectionUtils.rethrowRuntimeException(var4);throw new IllegalStateException(var4);}}}

原來是在這里進行了異常處理。通過在tryParse()方法傳入lambda表達式然后再call()返回(這一步并沒有進行實際業務執行,單純為了將處理異常這一步統一處理)。再判斷調用lambda時不活的異常是否是原業務的異常,如果不是就再爆其他的異常。

我們參照這個解決邏輯,完成一個在項目中使用的JacksonUtil類。

同時注意到在源碼部分對ObjectMapper這個一直用的對象進行了單例模式的實現,我們也學習一下。

1.單例模式實現ObjectMapper

    /*** 單例模式實現ObjectMapper*/private static final ObjectMapper OBJECT_MAPPER;static {OBJECT_MAPPER = new ObjectMapper();}//構造方法私有化private JacksonUtil() {}//獲取OBJECT_MAPPER對象public ObjectMapper getObjectMapper() {return JacksonUtil.OBJECT_MAPPER;}

2.解決try catch太多的方法

我們可以直接復制源碼部分的tryParse代碼

只需把final改為static(方便其他方法調用)

else判斷的部分也可以不要(jdk自己對異常的補充,可以不要)

    protected static <T> T tryParse(Callable<T> parser, Class<? extends Exception> check) {try {return parser.call();} catch (Exception var4) {if (check.isAssignableFrom(var4.getClass())) {throw new JsonParseException(var4);}throw new IllegalStateException(var4);}}

我們可以對這個方法進行封裝一下:

    /*** 封裝tryParse方法  使其固定爆出JacksonException異常* @param parser 傳入的lambda表達式* @param <T>* @return*/private final <T> T tryParse(Callable<T> parser) {return JacksonUtil.tryParse(parser, JacksonException.class);}

3.實現序列化

由于普通對象與List Map的序列化過程幾乎相同,所以我們一個方法就可以實現。

    /*** 序列化  對普通對象  與  List  都適用* @param object* @return*/public static String writeValueAsString(Object object) {return JacksonUtil.tryParse(() -> {return JacksonUtil.getObjectMapper().writeValueAsString(object);});}

4.實現反序列化

普通對象序列化:

    /*** 普通對象反序列化* @param content* @param valueType* @param <T>* @return*/public static <T> T readValue(String content, Class<T> valueType) {return JacksonUtil.tryParse(() -> {return JacksonUtil.getObjectMapper().readValue(content, valueType);});}

List反序列化:注意將第二個參數類型改為?Class<?>而不是??Class<T>

    /*** 反序列化  List* @param content* @param paramClasses* @param <T>* @return*/public static <T> T readListValue (String content, Class<?> paramClasses) {JavaType javaType = JacksonUtil.getObjectMapper().getTypeFactory().constructParametricType(List.class, paramClasses);return JacksonUtil.tryParse(() -> {return JacksonUtil.getObjectMapper().readValue(content, javaType);});}

最后附上測試代碼:

    @Testvoid jackUtilTest() {CommonResult<String> result = CommonResult.error(500, "系統錯誤");String str = JacksonUtil.writeValueAsString(result);System.out.println(str);CommonResult<String> commonResult = JacksonUtil.readValue(str, CommonResult.class);System.out.println(commonResult);//序列化 ListList<CommonResult<String>> list = Arrays.asList(CommonResult.success("success1"),CommonResult.success("success2"));String str1 = JacksonUtil.writeValueAsString(list);System.out.println(str1);list = JacksonUtil.readListValue(str1, CommonResult.class);for(CommonResult<String> a : list) {System.out.println(a.getData());}}

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/904232.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/904232.shtml
英文地址,請注明出處:http://en.pswp.cn/news/904232.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

筆試專題(十五)

文章目錄 排序子序列題解代碼 消減整數題解代碼 最長公共子序列(二)題解代碼 排序子序列 題目鏈接 題解 1. 貪心 模擬 2. 1 2 3 2 2 應該是有兩個排列子序列的&#xff0c;所以i n-1時ret 3. 把水平的位置和上升部分&#xff0c;水平位置和下降部分分為一個排列子序列 代…

Amazon Bedrock Converse API:開啟對話式AI新體驗

Amazon Bedrock Converse API&#xff1a;開啟對話式AI新體驗 前言 在當今人工智能飛速發展的時代&#xff0c;對話式AI已成為眾多應用的核心組成部分。從智能客服到智能助手&#xff0c;對話式AI為用戶帶來了便捷且高效的交互體驗。而Amazon Bedrock Converse API的出現&…

【Springboot知識】Springboot計劃任務Schedule詳解

文章目錄 Spring Boot 定時任務從原理到實現詳解一、核心原理分析1. 架構分層2. 核心組件3. 線程模型 二、基礎實現步驟1. 添加依賴2. 主類配置3. 定時任務類 三、高級配置技巧1. 自定義線程池2. 動態配置參數3. 分布式鎖集成&#xff08;Redis示例&#xff09; 四、異常處理機…

MySQL:聯合查詢

目錄 一、笛卡爾積 ?二、內連接 三、外連接 &#xff08;1&#xff09;左外連接 &#xff08;2&#xff09;右外連接 &#xff08;3&#xff09;全外連接 四、自連接 五、子查詢 &#xff08;1&#xff09;單行子查詢 &#xff08;2&#xff09;多行子查詢 &…

深入理解 Cortex-M3 的內核寄存器組

每個 MCU 開發工程師一定都了解寄存器這個東西&#xff0c;以 STM32 為例&#xff0c;其擁有非常多的外設模塊&#xff0c;如串口、SPI、IIC 等等&#xff0c;如果要使用這些外設&#xff0c;使其按照我們的要求工作&#xff0c;就需要配置這些外設的寄存器&#xff0c;往這些寄…

網絡安全自動化:找準邊界才能筑牢安全防線

數字時代&#xff0c;企業每天要面對成千上萬的網絡攻擊。面對龐大的服務器群、分散的團隊和長期不重啟的設備&#xff0c;很多企業開始思考&#xff1a;哪些安全操作適合交給機器自動處理&#xff1f;哪些必須由人工把關&#xff1f;今天我們就用大白話聊聊這件事。 一、這些事…

C++負載均衡遠程調用學習之負載均衡算法與實現

目錄 01 lars 系統架構回顧 02 lars-lbAgentV0.4-route_lb處理report業務流程 03 lars-lbAgentV0.4-負責均衡判斷參數配置 04 lars-lbAgentV0.4-負載均衡idle節點的失敗率判斷 05 lars-lbAgentV0.4-負載均衡overload節點的成功率判斷 06 lars-lbAgentV0.4-負載均衡上報提交…

領略算法真諦: 多源bfs

嘿&#xff0c;各位技術潮人&#xff01;好久不見甚是想念。生活就像一場奇妙冒險&#xff0c;而編程就是那把超酷的萬能鑰匙。此刻&#xff0c;陽光灑在鍵盤上&#xff0c;靈感在指尖跳躍&#xff0c;讓我們拋開一切束縛&#xff0c;給平淡日子加點料&#xff0c;注入滿滿的pa…

雷電模擬器-超好用的Windows安卓模擬器

一、雷電模擬器介紹 雷電模擬器是一款功能強大的軟件&#xff0c;它能夠在電腦上模擬出安卓手機系統&#xff0c;讓你可以在電腦上運行各類手機應用及游戲。其采用虛擬安卓手機操作界面&#xff0c;為玩家帶來了獨特的體驗。 &#xff08;一&#xff09;強大的兼容性 雷電模擬…

文章三《機器學習基礎概念與框架實踐》

文章3:機器學習基礎概念與框架實踐 ——從理論到代碼,用Scikit-learn構建你的第一個分類模型 一、機器學習基礎理論:三大核心類型 機器學習是人工智能的核心,通過數據讓計算機自動學習規律并做出預測或決策。根據學習方式,可分為三類: 1. 監督學習(Supervised Learni…

腦機接口技術:開啟人類與機器的全新交互時代

在科技飛速發展的今天&#xff0c;人類與機器的交互方式正經歷著前所未有的變革。從最初的鍵盤鼠標&#xff0c;到觸摸屏&#xff0c;再到語音控制&#xff0c;每一次交互方式的升級都極大地提升了用戶體驗和效率。如今&#xff0c;腦機接口&#xff08;Brain-Computer Interfa…

8.2 GitHub企業級PDF報告生成實戰:ReportLab高級技巧與性能優化全解析

GitHub企業級PDF報告生成實戰:ReportLab高級技巧與性能優化全解析 GitHub Sentinel 高級功能實現:PDF 報告生成技術詳解 關鍵詞:PDF 報告生成, ReportLab 實戰, 結構化數據轉換, 容器化字體配置, 企業級報告模板 1. 需求分析與技術選型 PDF 報告生成需要滿足以下技術要求…

架構思維:構建高并發讀服務_基于流量回放實現讀服務的自動化測試回歸方案

文章目錄 引言一、升級讀服務架構&#xff0c;為什么需要自動化測試&#xff1f;二、自動化回歸測試系統&#xff1a;整體架構概覽三、日志收集1. 攔截方式2. 存儲與優化策略3. 架構進化 四、數據回放技術實現關鍵能力 五、差異對比對比方式靈活配置 六、三種回放模式詳解1. 離…

基于Spring Boot 3.0、ShardingSphere、PostgreSQL或達夢數據庫的分庫分表

要實現基于Spring Boot 3.0、ShardingSphere、PostgreSQL或達夢數據庫的分庫分表&#xff0c;首先需要對ShardingSphere進行一些基本配置。你提到的溯源碼、批次號等數據需要考慮到跨年數據的存儲&#xff0c;因此要設計一個能夠動態擴展的分表策略 添加ShardingSphere依賴 在…

位運算的應用

1. 判斷偶數&#xff0c;判斷最低位是0還是1即可&#xff0c;?求模快 x % 2 ! 0 //x正負都可以判斷&#xff1b;不?x%2 1&#xff0c;因為如果x為負奇數&#xff0c;x%2-1 (x & 0x1) 0 例如&#xff1a; int x; int main() { cin>>x; if((x & 0x1)0) cout<…

FOC算法開環控制基礎

1. 為什么要有FOC算法 先看看從有刷電機到無刷電機的簡單介紹&#xff0c;如下圖1&#xff0c;通電螺線圈會產生磁場&#xff0c;這個磁場會產生N級和S級&#xff0c;然后這個電磁鐵就可以吸引永磁體&#xff0c;S級吸引N級&#xff0c;N級吸引S級&#xff0c;通俗的來說&…

【計算機網絡】HTTP中GET和POST的區別是什么?

從以下幾個方面去說明&#xff1a; 1.定義 2.參數傳遞方式 3.安全性 4.冪等性 1.定義&#xff1a; GET&#xff1a; 獲取資源&#xff0c;通常請求數據而不改變服務器的狀態。POST&#xff1a; 提交數據到服務器&#xff0c;通常會改變服務器的狀態或副作用(如創建或更新資源…

7400MB/s5050TBW完美結合,全新希捷酷玩530R SSD體驗評測

7400MB/s&5050TBW完美結合&#xff0c;全新希捷酷玩530R SSD體驗評測 哈嘍小伙伴們好&#xff0c;我是Stark-C~ 說到希捷酷玩530 SSD&#xff0c;很多硬核進階玩家應該都知道&#xff0c;或者說正在使用&#xff08;比如說我~&#xff09;。 作為希捷大廠旗下高性能SSD的…

(undone) MIT6.S081 2023 學習筆記 (Day11: LAB10 mmap)

url: https://pdos.csail.mit.edu/6.1810/2023/labs/mmap.html mmap和munmap系統調用允許UNIX程序對其地址空間進行精細控制。它們可用于進程間共享內存、將文件映射到進程地址空間&#xff0c;并作為用戶級頁面錯誤處理方案的一部分&#xff0c;例如課程中討論的垃圾回收算法。…

Q_OBJECT宏的作用

Qt 中&#xff0c;如果一個類中定義了信號&#xff08;signals&#xff09;或槽&#xff08;slots&#xff09;&#xff0c;那么這個類必須包含 Q_OBJECT 宏。 Q_OBJECT宏是 Qt 元對象系統的核心部分&#xff0c;它使得信號和槽機制能夠正常工作。 Q_OBJECT宏是 Qt 的元對象系統…