1. 引言

在 Java 应用中,JSON 是最常见的数据传输和存储格式之一。更小的 JSON 数据体积意味着更低的网络传输成本和更快的响应速度。

本文将介绍几种在 Java 应用中有效减少 JSON 数据大小的方法。

2. 领域模型与测试数据

我们定义一个简单的 Customer 类作为示例:

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 外,其他字段都是必填项。

为了真实模拟数据场景,我们使用 mockaroo 生成了 1000 条客户数据,字段结构与上述模型一致,部分字段允许为空:

  • 50% 的电话号码为空
  • 30% 的邮箱地址为空

后续所有示例代码均使用这 1000 条数据,并通过 Customer.fromMockFile() 方法加载为 Java 对象。

我们将使用 Jackson 作为 JSON 处理库。

3. 使用 Jackson 默认配置生成 JSON

使用 Jackson 默认配置将 Java 对象序列化为 JSON 字节数组:

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

第一条数据的 JSON 格式如下:

{
  "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]"
}

使用默认配置时,1000 条记录的 JSON 数据体积为 181.0 KB

4. 使用 gzip 压缩

JSON 是文本数据,非常适合使用 gzip 压缩。

✅ **对默认生成的 JSON 数据进行 gzip 压缩后,体积为 45.9 KB,仅占原始大小的 25.3%**。这意味着只需开启 gzip 压缩,就能在不改动 Java 代码的前提下节省 75% 的传输体积。

在 Spring Boot 应用中,可通过以下配置开启 gzip 压缩:

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

说明:

  • enabled: true:启用压缩
  • mime-types:指定压缩的 MIME 类型,包括 JSON
  • min-response-size:设置最小响应大小,避免压缩小数据反而增大体积

⚠️ 如果使用 JSON 作为存储格式,需要自行实现压缩和解压逻辑。

5. 使用更短的字段名

虽然不推荐,但在某些场景下(如存储)可考虑使用极短的字段名:

{
  "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 的 @JsonProperty 注解可实现字段名映射:

@JsonProperty("p")
private String postalCode;

✅ **使用单字符字段名后,JSON 数据体积为原始大小的 72.5%;gzip 压缩后为 23.8%**。

⚠️ 可读性大幅下降,仅适用于存储场景。

6. 序列化为数组格式

进一步减少字段名开销的方法是将对象序列化为数组:

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

✅ **使用数组格式后,JSON 数据体积为原始大小的 53.1%;gzip 压缩后为 22.0%**。

⚠️ 可读性差,需手动控制序列化逻辑。

7. 排除 null 值字段

Jackson 默认会输出值为 null 的字段。建议排除这些字段以减小体积:

✅ **排除 null 字段后,数据体积为原始大小的 92.1%;gzip 压缩后为 24.9%**。

如果再结合短字段名:

✅ **体积为原始大小的 68.3%;gzip 压缩后为 23.4%**。

可通过以下方式配置 Jackson 全局忽略 null 值:

mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);

8. 精简领域模型

通过减少字段数量,进一步压缩数据体积。

假设前端只需要显示客户姓名和地址,我们可以设计一个精简模型:

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

对应的 Java 类:

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

✅ **使用精简模型后,数据体积为原始大小的 46.1%;gzip 压缩后为 15.1%**。

如果再结合短字段名和数组序列化:

✅ **最终体积为原始大小的 34.2%;gzip 压缩后仅为 14.2%**。

9. 总结

方法 体积占比 gzip 后占比
默认 Jackson 100% 25.3%
gzip 压缩 - ✅ 25.3%
短字段名 72.5% 23.8%
数组序列化 53.1% 22.0%
排除 null 92.1% 24.9%
精简模型 46.1% 15.1%
精简 + 短字段 + 数组 34.2% ✅ 14.2%

📌 最佳实践建议

  • 生产环境务必开启 gzip 压缩(简单粗暴,收益高)
  • 存储场景可考虑短字段名或数组序列化
  • 针对特定前端设计精简模型,能显著减小体积
  • 排除 null 字段是通用优化手段

完整代码示例见:GitHub 项目地址


原始标题:Reducing JSON Data Size