1. 程式人生 > 程式設計 >JSON工具類的構建(後端版本)

JSON工具類的構建(後端版本)

前言

在前後端互動的選擇上,之前一直採用的是模板引擎(因為我只負責後端)。 而這次的一個算是作業吧,前後端都是我,所以就研究了一下JSON互動在java web的應用(主要是前端)。

優缺點

  • 前後端耦合

    • 模板引擎載入只是將jsp的互動方式移植到html上,前端檔案格式改變了,但是jsp中前後端耦合的缺點沒有改變。
    • json互動中,資料通過js/jquery動態載入在頁面上,資料與頁面進行分離,頁面只是單純用於展示。
  • 資料載入邏輯複用

    • 模板引擎的方式中,如果有很多相似的頁面元素以及一樣的資料返回格式,那只是複製貼上大法了。
    • 在模板引擎的例子中,只需要定義一套資料載入模型,傳入不同的頁面元素id以及資料則能實現邏輯複用
  • 後端介面的複用 因為我的學習路線的問題,所以我開發過安卓原生一段時間。

    • 模板引擎式的載入必須使用webView元件載入,且需另進行原生構建時介面也要另外構建。
    • json互動,谷歌爸爸鼓勵使用json進行互動(一年多前的事,現在不清楚了),且安卓原生內建GJSON進行json解析與構建,所以可以在原生以及跨平臺的構建有很好的平衡。

對比

既然選擇了json互動的方式,而java官方據我所知是沒有內建對json的支援,Spring在Controller的層面使用RestContrller註解實現對json的支援。 但是我個人強迫症很強,我對Contrller(或者說是Presenter)的定義是

  • 對使用者訪問的url作頁面的對映
  • 對使用者觸發的事件進行資料的傳遞與返回 正是這兩點的定義,我需要在Service層組合統一格式的結果返回到上層,所以需要第三方json支援。 可選擇的JSON庫有很多,GSON,FastJson,Jackson,根據對比,我選擇為馬老師充值一波。

需求拆分

我初步定義的需求主要有三個

  • Service傳遞統一處理結果到上層
  • 無論是單一資料實體或者List型資料處理的結果是一樣的
  • 處理過程是獨立的,不依賴於實體類的支援

格式設計

在網上看過很多後端返回資料的格式,很多都是返回一個處理的status以及具體的資料,而這個status是根據http狀態碼進行設定的,因為這次時間比較緊,所以我就採用了這個方案。

{
    "status": "status","object": {
        
    }
}
複製程式碼

程式碼設計

因為我希望Controller能直接拿到結果,所以構建結果的過程全放在Result類中。 而結果構建我主要分為兩種:只有狀態碼(通知處理結果)以及具有返回結果(資料顯示),而根據結果的個人也分為兩種:單個資料以及List型資料。

實際程式碼

@Getter
@Slf4j
public class ResultSet {

    private JSONObject result;

    public ResultSet(){
        result=new JSONObject();
    }

    /**
     * 初始化狀態碼
     * @param status
     */
    public void initStatus(String status){
        result.put("status",status);
    }

    /**
     * 初始化狀態碼以及返回資料
     * @param status
     * @param obj
     */
    public void initData(String status,Object obj){
        initStatus(status);
        if(obj instanceof List){
            List list=(List)obj;
            JSONArray array=new JSONArray();
            for(Object object:list){
                array.add(putObjectToJSON(object));
            }
            result.put("object",array);
        }
        else {
            result.put("object",putObjectToJSON(obj));
        }
    }

    /**
     * 將單個Object放入json檔案中
     * @param obj
     * @return
     */
    private JSONObject putObjectToJSON(Object obj){
        JSONObject result=new JSONObject();
        Field[] fields=obj.getClass().getDeclaredFields();
        for(Field field:fields){
            field.setAccessible(true);
            String fieldName=field.getType().getSimpleName();
            if(fieldName.equals("Department")||fieldName.equals("Job")){
                JSONObject tempJson=new JSONObject();
                try {
                    Object tempObject = field.get(obj);
                    Field[] tempFields=tempObject.getClass().getDeclaredFields();
                    for(Field tempField:tempFields){
                        tempField.setAccessible(true);
                        tempJson.put(tempField.getName(),tempField.get(tempObject));
                        tempField.setAccessible(false);
                    }
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
                if(fieldName.equals("Department")){
                    result.put("depart",tempJson);
                }
                else {
                    result.put("job",tempJson);
                }
            }
            else {
                try {
                    result.put(field.getName(),field.get(obj));
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }
            field.setAccessible(false);
        }
        return result;
    }
}
複製程式碼

程式碼思路

  1. Service通過initStatus/initData傳入資料/狀態碼進行物件的生成

  2. Controller通過result的getter方法獲取處理結果

  3. 單個資料以及List資料的處理

    1. 單個物件直接通過putObjectToJSON進行處理
    2. List資料通過物件型別判斷,向下轉型,遍歷元素形成JSONArray進行處理,對元素處理的方法也是採用putObjectToJSON
  4. 巢狀物件的處理

    public class Employee {
    
       private int id;
    
       private Department depart;
    
       private Job job;
    
       private String name;
    
    	..................
    }
    複製程式碼
    1. 通過反射獲取物件的所有成員變數型別以及對應的值
    2. 遇到上述bean類含有巢狀自定義物件時,遞迴生成json檔案加入到結果json中

結果演示

​ (左為單object型,右為List型)

不足之處

  1. 狀態碼的設定應該採用列舉類的賦值,能更好的約束返回的狀態碼
  2. 在物件轉換方面,應該採用配置掃描的方式。在配置檔案中寫入bean的包所在,在巢狀物件轉換時通過掃描配置檔案的資訊判斷
  3. 在巢狀物件的轉換方面,只是做了一層的巢狀轉換,更多層的沒有考慮到,之後會再重構的
  4. 對異常處理方面,只是簡單的輸出錯誤資訊。應該對錯誤資訊進行進一步的處理

後記

因為這次時間比較趕,從專案的立項到成品的建立花了5天時間,所以注意到很多細節,但是沒有去處理。 有想過之後有時間的話將這個工具類的細節完善起來,形成jar包供自己或者供開源。

相關連線

這只是後臺對結果的統一處理,我另外寫了一篇文章:JSON工具類的構建(前端版本),配合使用效果更佳哦~

本文首發於cartoon的部落格
轉載請註明出處:cartoonyu.github.io/cartoon-blo…