全棧之路-小程序API-Json數據類型的序列化與反序列化


  MySQL中有一種新的數據結構,就是json格式,在使用springboot中進行數據的讀取的時候往往會將json類型的數據直接轉換成字符串類型的數據,對於頁面的數據的處理很不友好,如何來將json類型的數據序列化成List或者Map類型的,七月老師提供了一整套的代碼完成以及思考過程,記錄一下整個代碼的優化過程

一、為什么要對這個進行優化?

1、這塊主要涉及的是sku表中的specs字段,這個字段的意義在於可以准確的確定是哪一件商品,比如:我需要的是(顏色:暗夜綠色,版本:256G全網通)的iPhone 11 Pro手機,其中暗夜綠色,全網通的iPhone 11 Pro手機就是一條sku數據,暗夜綠色,全網通版本就是specs字段所存儲的內容,我們在數據庫中是以json字段進行存儲的,我們不做處理的話,返回給前端的就是json字符串,

例如:"specs": "[{\"key\": \"顏色\", \"value\": \"橘黃色\", \"key_id\": 1, \"value_id\": 44}, {\"key\": \"圖案\", \"value\": \"七龍珠\", \"key_id\": 3, \"value_id\": 9}, {\"key\": \"尺碼\", \"value\": \"小號 S\", \"key_id\": 4, \"value_id\": 14}]"

雖然前端也是可以處理的,但是后台我們進行序列化之后,再返回給前端不是更加友好嗎?哈哈,真是貼心的后端開發者!!!
2、最完美的返回形式
"specs": [{"key_id": 1,"key": "顏色","value_id": 45, "value": "金屬灰" },{"key_id": 3, "key": "圖案","value_id": 9,"value": "七龍珠"},{"key_id": 4, "key": "尺碼","value_id": 14,"value": "小號 S"}],
這樣的話,前端開發人員可以直接讀取遍歷出想要的數據

 二、單體Json對象的映射處理

1、首先做一個單體Json對象與Map的轉換的工具類

注意:

(1)json序列化工具用的是jackson

(2)異常處理是拋出500錯誤,也就是服務器異常,做了一下異常處理的封裝(這里是把必須要處理的IO異常。轉換成RuntimeException)

(3)一定要加上@Converter注解

 1 @Converter
 2 public class MapAndJson implements AttributeConverter<Map<String, Object>, String> {
 3 
 4     @Autowired
 5     private ObjectMapper mapper;
 6 
 7     @Override
 8     public String convertToDatabaseColumn(Map<String, Object> stringObjectMap) {
 9         try {
10             return mapper.writeValueAsString(stringObjectMap);
11         } catch (JsonProcessingException e) {
12             e.printStackTrace();
13             throw new ServerErrorException(9999);
14         }
15     }
16 
17     @Override
18     public Map<String, Object> convertToEntityAttribute(String s) {
19         try {
20             if (s == null) {
21                 return null;
22             }
23             return mapper.readValue(s, HashMap.class);
24         } catch (JsonProcessingException e) {
25             e.printStackTrace();
26             throw new ServerErrorException(9999);
27         }
28     }
29 }

2、轉換字段中使用

1     @Convert(converter = MapAndJson.class)
2     private Map<String, Object> test;

三、數組類型json與List的映射

1、首先做一個數組類型Json與List轉換的工具類

注意:這個工具類基本上和單體Json與Map映射很類似

 1 @Converter
 2 public class ListAndJson implements AttributeConverter<List<Object>, String> {
 3 
 4     @Autowired
 5     private ObjectMapper mapper;
 6 
 7     @Override
 8     public String convertToDatabaseColumn(List<Object> objects) {
 9         try {
10             return mapper.writeValueAsString(objects);
11         } catch (JsonProcessingException e) {
12             e.printStackTrace();
13             throw new ServerErrorException(9999);
14         }
15     }
16 
17     @Override
18     public List<Object> convertToEntityAttribute(String s) {
19         try {
20             if (s == null) {
21                 return null;
22             }
23             return mapper.readValue(s, List.class);
24         } catch (JsonProcessingException e) {
25             e.printStackTrace();
26             throw new ServerErrorException(9999);
27         }
28     }
29 
30 }

2、字段中使用

1     @Convert(converter = ListAndJson.class)
2     private List<Object> specs;

四、更優的解決方案

以上兩個方法存在的問題是:沒有辦法確定具體的業務對象,就是一個Map,或者是List<Object>,沒有辦法確定到底是哪種業務對象,就像我們這里所要的,我們想要的是List<Spec>這種具體的Spec的對象的集合,這樣的話,更加符合面向對象的思想,而且即使后面我們調用Spec具體對象中的業務方法的時候會更加方便,所以有必要做一個更加的優化方案!

1、創建一個通用的序列化反序列化工具類

注意:這里很不好理解的,只有對泛型比較熟悉,才能很容易理解,至於寫出這種代碼,我覺得目前還是寫不出來的

 1 @Component
 2 public class GenericAndJson {
 3 
 4     private static ObjectMapper mapper;
 5 
 6     // 這里用到的set方法的自動注入,實例化static變量
 7     @Autowired
 8     public void setMapper(ObjectMapper mapper) {
 9         GenericAndJson.mapper = mapper;
10     }
11 
12     public static <T> String objectToJson(T o) {
13         try {
14             return GenericAndJson.mapper.writeValueAsString(o);
15         } catch (JsonProcessingException e) {
16             e.printStackTrace();
17             throw new ServerErrorException(9999);
18         }
19     }
20 
21     public static <T> T jsonToObject(String s, TypeReference<T> tr) {
22         try {
23             if (s == null) {
24                 return null;
25             }
26             return GenericAndJson.mapper.readValue(s, tr);
27         } catch (JsonProcessingException e) {
28             e.printStackTrace();
29             throw new ServerErrorException(9999);
30         }
31     }
32 
33 }

2、實際中使用

注意:需要重寫變量的set與get方法,來進行序列化與反序列化操作

 1     private String specs;
 2 
 3     public List<Spec> getSpecs() {
 4         if(this.specs == null){
 5             return Collections.emptyList();
 6         }
 7         return GenericAndJson.jsonToObject(this.specs, new TypeReference<List<Spec>>() {
 8         });
 9     }
10 
11     public void setSpecs(List<Spec> specs) {
12         if(specs.isEmpty()){
13             return;
14         }
15         this.specs = GenericAndJson.objectToJson(specs);
16     }

 

 

 

 內容出處:七月老師《從Java后端到全棧》視頻課程

七月老師課程鏈接:https://class.imooc.com/sale/javafullstack


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM