FastJSON 默認行為:JSON.toJSONString 忽略 null 字段

完整的 FakeRegistrationController 代碼,這讓我可以全面分析后端邏輯,特別是為什么空的字段(如 compareDate)不返回給前端。我將詳細分析代碼的每個接口,尤其是與 list 請求和字段返回相關的部分,并解釋原因。


代碼結構總覽

FakeRegistrationController 是一個 RESTful 控制器,提供了三個接口:

  1. POST /fakeRegistration/registration/save:保存或修改假貨登記信息。
  2. POST /fakeRegistration/compare/save:保存或修改比對結果。
  3. GET /fakeRegistration/list:獲取假貨登記列表(對應前端的 qlist 請求)。

我們關心的是 list 接口,因為它直接決定了前端表格接收到的數據內容,特別是為何空的 compareDate 不返回。


詳細分析 list 接口

接口定義
@GetMapping("list")
@ApiOperation("假貨登記列表")
public BaseResult list(@ApiIgnore @SessionAttribute(Constants.ADMIN_ID) Integer adminId,BasePage page) {Integer vipAdminId = copywritingApiService.getVipAdminId(adminId, 11);Page<FakeRegistration> fakeRegistrationPage = fakeRegistrationService.findByAdminId(vipAdminId, page);List<FakeRegistration> fakeRegistrations = fakeRegistrationPage.getContent();List<FakeRegistrationListDTO> fakeRegistrationListDTOS = new ArrayList<>();for (FakeRegistration fakeRegistration: fakeRegistrations) {FakeRegistrationListDTO fakeRegistrationListDTO = JSON.parseObject(JSON.toJSONString(fakeRegistration), FakeRegistrationListDTO.class);if (null != fakeRegistration.getProductId()) {Product product = productService.findById(fakeRegistration.getProductId()).orElseThrow(() -> new RuntimeException("未找到商品信息"));fakeRegistrationListDTO.setProductName(product.getName());}Admin creator = adminService.findById(fakeRegistration.getCreatorId()).orElseThrow(() -> new RuntimeException("未找到創建人信息"));fakeRegistrationListDTO.setCreatorName(StringUtils.isEmpty(creator.getNickname()) ? creator.getUsername() : creator.getNickname());fakeRegistrationListDTO.setGenuineIdentificationPoints(fakeRegistrationApiService.findIdentification(fakeRegistration.getId(), 1));fakeRegistrationListDTO.setFakeIdentificationPoints(fakeRegistrationApiService.findIdentification(fakeRegistration.getId(), 0));fakeRegistrationListDTOS.add(fakeRegistrationListDTO);}return BaseResult.success(new PageImpl<>(fakeRegistrationListDTOS, PageRequest.of(fakeRegistrationPage.getNumber(), fakeRegistrationPage.getSize()), fakeRegistrationPage.getTotalElements()));
}
數據流分析
  1. 數據查詢

    • fakeRegistrationService.findByAdminId(vipAdminId, page) 返回一個 Page<FakeRegistration>,其中 FakeRegistration 是數據庫實體類,包含所有字段(如 id, createdDate, compareDate, comparisonStatus 等)。
    • fakeRegistrations 是分頁內容的 List<FakeRegistration>
  2. 數據轉換

    • 每個 FakeRegistration 被轉換為 FakeRegistrationListDTO
      FakeRegistrationListDTO fakeRegistrationListDTO = JSON.parseObject(JSON.toJSONString(fakeRegistration), FakeRegistrationListDTO.class);
      
    • 這里使用了 FastJSON(com.alibaba.fastjson.JSON)進行序列化和反序列化:
      • JSON.toJSONString(fakeRegistration)FakeRegistration 轉為 JSON 字符串。
      • JSON.parseObject(..., FakeRegistrationListDTO.class) 將 JSON 字符串轉為 FakeRegistrationListDTO 對象。
    • 然后手動補充了:
      • productName:從 ProductService 獲取。
      • creatorName:從 AdminService 獲取。
      • genuineIdentificationPointsfakeIdentificationPoints:從 FakeRegistrationApiService 獲取。
  3. 返回結果

    • 返回一個 PageImpl<FakeRegistrationListDTO>,最終被序列化為 JSON 響應。
為什么空的字段(如 compareDate)不返回?
  • FastJSON 的默認行為

    • FastJSON 在序列化時,默認忽略 null 值字段,除非顯式配置 SerializerFeature.WriteMapNullValue
    • 如果 FakeRegistrationcompareDatenullJSON.toJSONString(fakeRegistration) 生成的 JSON 字符串不會包含 "compareDate"
    • 示例:
      FakeRegistration fr = new FakeRegistration();
      fr.setId(34);
      fr.setComparisonStatus(1);
      fr.setCompareDate(null); // 為空
      String json = JSON.toJSONString(fr);
      // 輸出: {"id":34,"comparisonStatus":1}
      
    • 反序列化到 FakeRegistrationListDTO 時,由于 JSON 中沒有 compareDatefakeRegistrationListDTOcompareDate 字段不會被賦值,最終返回的 JSON 也不會包含它。
  • 業務邏輯

    • 從其他接口看,compareDate 只有在 compare/save 接口保存比對結果時才會設置:
      fakeRegistrationOrigin.setCompareDate(new Date());
      
    • registration/save 接口中,新建記錄時沒有設置 compareDate,它保持為 null
    • 因此,未完成比對的記錄(comparisonStatus = 01)在數據庫中 compareDate 就是 NULL,序列化后被忽略。
  • DTO 定義的影響

    • 如果 FakeRegistrationListDTO 中定義了 compareDate
      public class FakeRegistrationListDTO {private Integer id;private Date compareDate; // 假設是這樣// 其他字段
      }
      
    • JSON.parseObject 處理沒有 compareDate 的 JSON 時,fakeRegistrationListDTO.compareDate 會是 null,但后續的序列化(返回給前端時)仍由 FastJSON 處理,又會被忽略。

其他接口的補充分析

1. registration/save
@PostMapping("registration/save")
public BaseResult save(@RequestBody FakeRegistration fakeRegistration, ...) {if(null != fakeRegistration.getId()) {FakeRegistration fakeRegistrationOrigin = fakeRegistrationService.findById(fakeRegistration.getId()).orElseThrow(...);fakeRegistration = SqlUtil.mergeObject(fakeRegistration, fakeRegistrationOrigin);if(null != fakeRegistration.getCompareResult() && fakeRegistration.getCompareResult() == 1) {fakeRegistrationOrigin.setComparisonStatus(3);} else if(null != fakeRegistration.getCompareResult() && fakeRegistration.getCompareResult() == 0) {fakeRegistrationOrigin.setComparisonStatus(2);}} else {fakeRegistration.setAdminId(vipAdminId);fakeRegistration.setCreatorId(adminId);}fakeRegistration = fakeRegistrationService.save(fakeRegistration);...
}
  • 關鍵點
    • 新建記錄時(fakeRegistration.getId() == null),只設置了 adminIdcreatorId,沒有初始化 compareDate,它默認為 null
    • 修改記錄時,如果提供了 compareResult,會更新 comparisonStatus,但不會設置 compareDate
    • 因此,compareDate 在這個接口中始終不會被賦值。
2. compare/save
@PostMapping("compare/save")
public BaseResult compareSave(@RequestBody FakeRegistrationSaveDTO fakeRegistration, ...) {FakeRegistration fakeRegistrationOrigin = fakeRegistrationService.findById(fakeRegistration.getId()).orElseThrow(...);fakeRegistrationOrigin.setCompareResult(fakeRegistration.getCompareResult());fakeRegistrationOrigin.setCompareDate(new Date());fakeRegistrationService.save(fakeRegistrationOrigin);...
}
  • 關鍵點
    • 這里顯式設置了 compareDate = new Date(),表示比對完成的時間。
    • 只有通過這個接口保存比對結果時,compareDate 才會被賦值。
    • 這解釋了前端數據中,只有 comparisonStatus = 2 或更高狀態的記錄有 compareDate

綜合結論:為什么空的字段不返回?

  1. 數據來源

    • compareDate 在數據庫中默認為 NULL,除非通過 compare/save 接口保存比對結果時才會被賦值。
    • 未完成比對的記錄(comparisonStatus = 01)沒有 compareDate 值。
  2. FastJSON 序列化

    • list 接口中,JSON.toJSONString(fakeRegistration)FakeRegistration 轉為 JSON 時,默認忽略 null 字段。
    • 如果 compareDatenull,它不會出現在 JSON 字符串中。
    • 反序列化到 FakeRegistrationListDTO 后,compareDate 仍未被賦值,最終返回的 JSON 也不包含這個字段。
  3. 業務邏輯

    • 設計上,compareDate 只有在比對完成時才有意義,未完成時保持 null 并被忽略是合理的。
  4. 最終返回

    • Spring Boot 的 @RestController 使用 Jackson(或其他配置)將 PageImpl<FakeRegistrationListDTO> 序列化為 JSON,同樣忽略 null 字段,進一步確保空的 compareDate 不出現在響應中。

前端數據的驗證

你的前端數據:

  • id: 34, 33, 32comparisonStatus = 01):沒有 compareDate,因為未調用 compare/save
  • id: 31, 30, 28comparisonStatus = 2):有 compareDate,因為通過 compare/save 設置了值。

改進建議

如果希望空的 compareDate 也返回(例如 "compareDate": null):

  1. 修改 FastJSON 配置

    FakeRegistrationListDTO fakeRegistrationListDTO = JSON.parseObject(JSON.toJSONString(fakeRegistration, SerializerFeature.WriteMapNullValue),FakeRegistrationListDTO.class
    );
    
    • 添加 WriteMapNullValue,確保 null 字段被包含。
  2. 調整 DTO

    • FakeRegistrationListDTO 中顯式處理:
      fakeRegistrationListDTO.setCompareDate(fakeRegistration.getCompareDate() != null ? fakeRegistration.getCompareDate() : null);
      
  3. 全局配置

    • 在 Spring Boot 中配置 Jackson:
      @Bean
      public ObjectMapper objectMapper() {ObjectMapper mapper = new ObjectMapper();mapper.setSerializationInclusion(JsonInclude.Include.ALWAYS);return mapper;
      }
      

總結

空的 compareDate 不返回給前端是因為:

  • 業務邏輯:未完成比對時,數據庫中 compareDateNULL
  • FastJSON 默認行為JSON.toJSONString 忽略 null 字段。
  • 設計選擇:后端選擇不返回無意義的空字段。

這種行為是合理的,但如果前端需要一致性,可以通過上述方式調整后端返回。

在這里插入圖片描述

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

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

相關文章

大模型基礎概念之神經網絡寬度

在大模型中,神經網絡寬度是提升模型容量的核心手段之一,與深度、數據規模共同構成性能的三大支柱。合理增加寬度可顯著增強模型表達能力,但需結合正則化、硬件優化和結構設計進行平衡。未來趨勢可能包括動態寬度調整、稀疏化寬度設計(如MoE)以及更高效寬度-深度復合縮放策…

在Linux環境下利用MTCNN進行人臉檢測(基于ncnn架構)

概述 本文將詳細介紹如何在Linux環境下部署MTCNN模型進行人臉檢測&#xff0c;并使用NCNN框架進行推理。 1. CMake的安裝與配置 下載CMake源碼 前往CMake官網下載&#xff0c;找到適合您系統的最新版本tar.gz文件鏈接&#xff0c;或者直接通過wget下載&#xff1a;CMake官方…

算法day1 dfs搜索2題

一 火星人 拿到這種類似于排序的&#xff0c;這個就好比如我們之前學習dfs基礎的時候里面的指數型枚舉 指數型枚舉數據與數據之間沒有任何枚舉&#xff0c;就比如選這個數字與不選組合型枚舉數據與數據之間有聯系&#xff0c;下一個數字不可以給上一個數字排列型枚舉數據與數…

CC攻擊防御策略全解析:技術實現與代碼示例

CC攻擊&#xff08;Challenge Collapsar&#xff09;是一種以消耗服務器資源為目標的分布式拒絕服務攻擊&#xff08;DDoS&#xff09;&#xff0c;其特點在于攻擊流量偽裝成合法請求&#xff0c;難以通過傳統防火墻完全防御。本文將從技術實現角度詳細解析CC攻擊的防御策略&am…

(九)axios的使用

1、axios 的基本使用 1.1、簡介 在 Web 開發的演進歷程中&#xff0c;數據請求方式的變革至關重要。回溯早期&#xff0c;舊瀏覽器在向服務器請求數據時&#xff0c;存在嚴重弊端。由于返回的是整個頁面數據&#xff0c;每次請求都會導致頁面強制刷新&#xff0c;這不僅極大地…

【MySQL篇】數據庫基礎

目錄 1&#xff0c;什么是數據庫&#xff1f; 2&#xff0c;主流數據庫 3&#xff0c;MySQL介紹 1&#xff0c;MySQL架構 2&#xff0c;SQL分類 3&#xff0c;MySQL存儲引擎 1&#xff0c;什么是數據庫&#xff1f; 數據庫&#xff08;Database&#xff0c;簡稱DB&#xf…

網絡安全事件研判

&#x1f345; 點擊文末小卡片 &#xff0c;免費獲取網絡安全全套資料&#xff0c;資料在手&#xff0c;漲薪更快 研判&#xff08;入侵檢測&#xff09; 研判我理解為人工層面對入侵檢測事件進行再分析&#xff0c;即借助已有的設備告警根據經驗判斷是否為真實action 研判工作…

python整理文件下

我們使用 os.path.join() 函數拼接出文件要移動的目標地址。 并使用 os.path.exists() 函數配合 not 關鍵字找到未創建的文件夾。 這節課&#xff0c;我們會先創建文件夾&#xff0c;然后再移動文件到目標文件夾。如果文件夾不存在&#xff0c;我們需要先創建文件夾&#xff…

hackmyvm-buster

題目地址 信息收集 主機發現 ┌──(root?kali)-[/home/kali] └─# arp-scan -I eth1 192.168.56.0/24 Interface: eth1, type: EN10MB, MAC: 00:0c:29:34:da:f5, IPv4: 192.168.56.103 WARNING: Cannot open MAC/Vendor file ieee-oui.txt: Permission denied WARNING: C…

FS800DTU聯動OneNET平臺數據可視化View

目錄 1 前言 2 環境搭建 2.1 硬件準備 2.2 軟件環境 2.3 硬件連接 3 注冊OneNET云平臺并建立物模型 3.1 參數獲取 3.2 連接OneNET 3.3上報數據 4 數據可視化View 4.1 用戶信息獲取 4.2 啟用數據可視化View 4.3 創建項目 4.4 編輯項目 4.5 新增數據源 4.6 數據過濾器配置 4.6 項…

Dockerfile 中的 COPY 語句:作用與使用詳解

在 Docker 的構建過程中&#xff0c;Dockerfile 是一個核心文件&#xff0c;它定義了鏡像的構建步驟和內容。其中&#xff0c;COPY 語句是一個非常重要的指令&#xff0c;用于將文件或目錄從構建上下文&#xff08;通常是 Dockerfile 所在的目錄及其子目錄&#xff09;復制到容…

大白話Vuex 核心概念(state、mutations、actions)的使用案例與原理

大白話Vuex 核心概念&#xff08;state、mutations、actions&#xff09;的使用案例與原理 Vuex是Vue.js應用程序中專門用來管理狀態的工具&#xff0c;就好像是一個大管家&#xff0c;幫你把項目里一些重要的數據和操作管理得井井有條。下面用大白話結合案例來介紹Vuex核心概…

機器學習介紹與數據集

一、機器學習介紹與定義 1.1 機器學習定義 機器學習&#xff08;Machine Learning&#xff09;是讓計算機從數據中自動學習規律&#xff0c;并依據這些規律對未來數據進行預測的技術。它涵蓋聚類、分類、決策樹、貝葉斯、神經網絡、深度學習&#xff08;Deep Learning&#xf…

大模型訓練——pycharm連接實驗室服務器

一、引言 我們在運行或者復現大佬論文代碼的時候&#xff0c;筆記本的算力不夠&#xff0c;需要使用實驗室的服務器進行運行。可以直接在服務器的終端上執行&#xff0c;但是這樣的話代碼調試就不方便。而我們可以使用 pycharm 連接到服務器&#xff0c;既方便了代碼調試&…

【Linux】進程優先級 | 進程調度(三)

目錄 前言&#xff1a; 一、進程優先級&#xff1a; 1.通過nice值修改優先級&#xff1a; 二、進程切換&#xff1a; 三、上下文數據 四、Linux真實調度算法&#xff1a; 五、bitmap位圖&#xff1a; 六、命令總結&#xff1a; 總結&#xff1a; 前言&#xff1a; 我…

【redis】數據類型之hyperloglog

Redis的HyperLogLog&#xff08;HLL&#xff09;是一種高效的概率數據結構&#xff0c;也是一種基于字符串的數據結構&#xff0c;用于估計大數據集的唯一元素數量&#xff08;基數統計&#xff09;。它通過極低的內存占用&#xff08;約 12KB&#xff09;實現接近線性的時間復…

【C語言】第八期——指針、二維數組與字符串

目錄 1 初始指針 2 獲取變量的地址 3 定義指針變量、取地址、取值 3.1 定義指針變量 3.2 取地址、取值 4 對指針變量進行讀寫操作 5 指針變量作為函數參數 6 數組與指針 6.1 指針元素指向數組 6.2 指針加減運算&#xff08;了解&#xff09; 6.2.1 指針加減具體數字…

SpringBoot——生成Excel文件

在Springboot以及其他的一些項目中&#xff0c;或許我們可能需要將數據查詢出來進行生成Excel文件進行數據的展示&#xff0c;或者用于進行郵箱發送進行附件添加 依賴引入 此處demo使用maven依賴進行使用 <dependency><groupId>org.apache.poi</groupId>&…

mac 下 java 調用 gurobi 不能加載 jar

在 mac 電腦中的 java 始終不能加載 gurobi 的 jar 包&#xff0c;java 的開發軟件 eclipse&#xff0c;idea 總是顯示找不到 gurobi 的 jar 包&#xff0c;但是 jar 包明明就在那里。 摸索了三個小時&#xff0c;最后發現原因竟然是&#xff1a; jar 包太新&#xff0c;替換…

服務端配置TCP探活,超出探活時間后的行為?

server端啟動 &#xff08;完整源碼在最后&#xff09; 配置探活 setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPIDLE, &(int){5}, sizeof(int)); // 空閑60秒后探測setsockopt(client_fd, IPPROTO_TCP, TCP_KEEPINTVL, &(int){10}, sizeof(int)); // 探測間隔10秒…