知識庫 / JSON / Jackson RSS 訂閱

減少 JSON 數據大小

Jackson,JSON
HongKong
6
09:51 PM · Dec 05 ,2025

1. 簡介

Java 應用程序經常使用 JSON 作為一種常見的格式,用於發送和接收數據。此外,它還被用作存儲數據的序列化協議。 隨着 JSON 數據體積的減小,我們的應用程序將更加經濟高效且速度更快。

在本教程中,我們將探討各種減少 Java 應用程序中 JSON 大小的方法。

2. 領域模型和測試數據

讓我們為 客户 創建一個領域模型,幷包含一些聯繫數據:

public class Customer {
    private long id;
    private String firstName;
    private String lastName;
    private String street;
    private String postalCode;
    private String city;
    private String state;
    private String phoneNumber;
    private String email;

請注意,所有字段都必須填寫,除了 phoneNumberemail 字段。

為了正確測試 JSON 數據大小差異,我們需要至少幾百個 Customer 實例。這些實例必須具有不同的數據,以使我們的測試更具真實性。數據生成網站 mockaroo 可以幫助我們。我們可以在那裏免費創建 1,000 條 JSON 數據記錄,使用我們自己的格式和真實測試數據。

讓我們為我們的領域模型配置 mockaroo

這裏有一些需要注意的事項:

  • 這裏我們指定了字段名稱
  • 在這裏我們選擇了字段的數據類型
  • mock 數據中 50% 的電話號碼為空
  • 電子郵件地址的 30% 也為空

以下所有代碼示例都使用來自 mockaroo 的 1,000 個客户數據。我們使用工廠方法 Customer.fromMockFile() 讀取該文件並將其轉換為 Customer 對象。

我們將使用 Jackson 作為我們的 JSON 處理庫。

3. 使用 Jackson 默認選項的 JSON 數據大小

讓我們使用 Jackson 默認選項將 Java 對象轉換為 JSON:

Customer[] customers = Customer.fromMockFile();
ObjectMapper mapper = new ObjectMapper();
byte[] feedback = mapper.writeValueAsBytes(customers); 

讓我們查看第一個 Customer 的模擬數據:

{
  "id" : 1, 
  "firstName" : "Horatius", 
  "lastName" : "Strognell", 
  "street" : "4848 New Castle Point", 
  "postalCode" : "33432", 
  "city" : "Boca Raton", 
  "state" : "FL", 
  "phoneNumber" : "561-824-9105", 
  "email" : "[email protected]"
}

使用默認 Jackson 選項時,包含所有 1,000 名客户的 JSON 數據字節數組大小為 181.0 KB.

4. 使用 gzip 壓縮

文本數據和 JSON 數據壓縮效果良好。因此,gzip 是我們首選的選項,用於減小 JSON 數據的大小。此外,它可以在 HTTP 中自動應用,HTTP 是發送和接收 JSON 的常用協議。

讓我們以使用默認 Jackson 選項生成的 JSON 進行壓縮,並使用 gzip 。結果為 45.9 KB,僅佔原始大小的 25.3%。因此,如果我們通過配置啓用 gzip 壓縮,我們可以在不修改 Java 代碼的情況下將 JSON 數據大小減少 75%!

如果我們的 Spring Boot 應用程序將 JSON 數據傳遞給其他服務或前端,那麼我們將在 Spring Boot 配置中啓用 gzip 壓縮。以下是一個典型的壓縮配置,使用 YAML 語法:

server:
  compression:
    enabled: true
    mime-types: text/html,text/plain,text/css,application/javascript,application/json
    min-response-size: 1024

首先,我們通過將 enabled 設置為 true 來啓用通用壓縮。然後,我們通過將 application/json 添加到 mime-types 列表中來啓用 JSON 數據壓縮。最後,請注意,我們設置了 min-response-size 為 1024 字節。這是因為如果壓縮少量數據,我們可能會產生比原始數據更大的數據。

例如,NGINX (https://www.nginx.com) 或 Apache HTTP Server (https://httpd.apache.org) 這樣的代理服務器經常將 JSON 數據傳遞給其他服務或前端。配置 JSON 數據壓縮在這些工具中超出了本教程的範圍。

在之前的關於 gzip (gzip) 的教程中,我們瞭解到 gzip 具有多種壓縮級別。我們的代碼示例使用 gzip 採用默認的 Java 壓縮級別。Spring Boot、代理服務器或 Web 服務器可能會針對相同 JSON 數據產生不同的壓縮結果。

如果使用 JSON 作為序列化協議來存儲數據,則需要自己壓縮和解壓縮數據。

5. JSON 中更短的字段名稱

建議使用既不短也不長的字段名稱。為了演示目的,我們暫時不採用此做法:我們將使用單字符的字段名稱在 JSON 中,但不會更改 Java 字段名稱。 這樣做會減少 JSON 數據的大小,但會降低 JSON 的可讀性。 此外,這也將需要更新所有服務和前端,因此我們可能只會將這些短字段名稱用於存儲數據時。

{
  "i" : 1,
  "f" : "Horatius",
  "l" : "Strognell",
  "s" : "4848 New Castle Point",
  "p" : "33432",
  "c" : "Boca Raton",
  "a" : "FL",
  "o" : "561-824-9105",
  "e" : "[email protected]"
}

使用 Jackson 更改 JSON 字段名稱時,Java 字段名稱將保持不變。我們將使用 @JsonProperty 註解:

@JsonProperty("p")
private String postalCode;

使用單字符字段名會導致數據大小減小72.5%。 此外,使用 gzip 可以將其壓縮至 23.8%。 這比僅使用 gzip 壓縮原始數據時獲得的 25.3% 略有減少。 我們始終需要尋找合適的成本效益關係。 為了獲得很小的尺寸優勢,在大多數情況下,犧牲可讀性並不值得推薦。

6. 將 JSON 數據序列化為數組

讓我們看看如何通過完全省略字段名稱來進一步減小 JSON 數據的大小。我們可以通過將 customers 數組存儲在我們的 JSON 中來實現這一點。請注意,這樣做也會降低可讀性,並且我們需要更新所有使用我們 JSON 數據的服務和前端。

[ 1, "Horatius", "Strognell", "4848 New Castle Point", "33432", "Boca Raton", "FL", "561-824-9105", "[email protected]" ]

客户存儲為數組會導致輸出大小為原始大小的53.1%,使用gzip壓縮後則為22.0%。這是我們目前為止的最佳結果。然而,22%與我們僅通過使用gzip壓縮原始數據獲得的25.3%相比,並沒有顯著縮小。

為了將客户序列化為數組,我們需要對JSON序列化進行完全控制。請再次參考我們的Jackson教程以獲取更多示例。

7. 排除 null

Jackson 和其他 JSON 處理庫在讀取或寫入 JSON 時,可能無法正確處理 JSON 中的 null 值。例如,Jackson 默認情況下會寫入 JSON 中的 null 值,當它遇到 Java 中的 null 值時。因此,建議在 JSON 數據中刪除空字段,這會將空值的初始化留給每個 JSON 處理庫,並減少 JSON 數據的大小。

在我們的模擬數據中,我們將 50% 的電話號碼和 30% 的電子郵件地址設置為為空。 排除這些 null 值將我們的 JSON 數據大小減少到 166.8KB 或原始數據大小的 92.1%。 然後,gzip 壓縮將將其減少到 24.9%。

現在,如果我們結合忽略 null 值與上一節中較短的字段名稱,那麼我們將獲得更大的節省:原始大小的 68.3% 和使用 gzip 時 23.4%。

我們可以配置 Jackson 中排除 null 值字段的方式,按類或對所有類進行全局配置。

8. 新域名類

我們通過將其序列化為數組,實現了迄今為止最小的 JSON 數據大小。 進一步減少數據大小的一種方法是引入新的領域模型,減少字段數量。但為什麼要做這件事呢?

假設我們有一個用於顯示所有客户的表單,該表單具有兩列:姓名和街道地址。 讓我們編寫專門為該表單設計的 JSON 數據:

{
  "id" : 1,
  "name" : "Horatius Strognell",
  "address" : "4848 New Castle Point, Boca Raton FL 33432"
}

請注意,我們如何將姓名字段連接到 name,以及地址字段連接到 address。此外,我們省略了 emailphoneNumber

這應該產生更小的 JSON 數據。它還避免了前端將 Customer 字段連接起來。但另一方面,它緊密地將後端與前端耦合。

讓我們為前端創建一個新的領域類 CustomerSlim

public class CustomerSlim {
    private long id;
    private String name;
    private String address;

如果我們將測試數據轉換為新的 CustomerSlim領域類,將使其減少到原始數據的46.1%。這將使用默認的 Jackson 設置。如果我們使用 gzip,則減少到15.1%。這個結果已經比之前的最佳結果(22.0%)有了顯著提升。

接下來,如果我們同時使用單字符字段名稱,則將減少到原始數據的40.7%,使用 gzip 進一步減少到14.7%。這個結果僅比我們使用 Jackson 默認設置時達到15.1% 的小幅提升。

CustomerSlim 中的沒有字段是可選的,因此省略空值不會影響 JSON 數據的大小。

我們的最後一個優化是序列化數組。 通過將 CustomerSlim 序列化為數組,我們實現了最佳結果:原始數據的34.2% 和使用 gzip 時為14.2%。 即使不進行壓縮,我們也能去除原始數據的近三分之二! 壓縮則將我們的 JSON 數據縮小到原始數據的七分之一!

9. 結論

在本文中,我們首先了解了減少 JSON 數據大小的必要性。接下來,我們學習了各種減少 JSON 數據大小的方法。最後,我們學習瞭如何使用針對特定前端的自定義領域模型進一步減少 JSON 數據大小。

user avatar
0 位用戶收藏了這個故事!
收藏

發佈 評論

Some HTML is okay.