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;
其中,除了 phoneNumber
和 email
外,其他字段都是必填项。
为了真实模拟数据场景,我们使用 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 类型,包括 JSONmin-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 项目地址