Skip to content

序列化方案对比

选型会议上,团队争论不休:

「用 JSON,调试方便」「用 Protobuf,性能好」「用 Kryo,Java 专用最快」「用 Java 原生,最简单」

到底选哪个?这一节给你一张清晰的选型地图。

方案总览

特性Java 原生JSONProtocol BuffersKryo
格式二进制文本二进制二进制
体积极小
性能较慢最快
跨语言
自描述✅(.proto)
序列化IDserialVersionUID字段编号
依赖JDK 原生Jackson/Gsonprotobuf 库Kryo 库

详细对比

Java 原生序列化

优点

  • JDK 原生,无需任何依赖
  • 自动处理引用关系(循环引用)
  • 支持版本兼容(serialVersionUID)
  • 自动处理对象图序列化

缺点

  • 体积大(含类信息、引用表)
  • 速度慢(反射调用、对象表维护)
  • 不跨语言(Java 专用格式)
java
// 序列化:JDK 原生
try (ObjectOutputStream oos = new ObjectOutputStream(
        new FileOutputStream("data.obj"))) {
    oos.writeObject(user);
}

JSON(Jackson / Gson)

优点

  • 人类可读,方便调试
  • 跨语言,Web API 标配
  • 生态丰富,工具链成熟

缺点

  • 体积大(文本格式,含字段名)
  • 需要类型信息
  • 性能比二进制差
java
// Jackson
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(user); // 序列化
User u = mapper.readValue(json, User.class);   // 反序列化

// Gson
Gson gson = new Gson();
String json = gson.toJson(user);
User u = gson.fromJson(json, User.class);

Protocol Buffers(Protobuf)

优点

  • 体积极小(字段用编号而非名称)
  • 性能快(编译时代码生成,无反射)
  • 跨语言(.proto 定义接口)
  • 向后兼容性好(字段编号机制)

缺点

  • 需要预先定义 .proto 文件
  • 需要编译步骤
  • 对于简单场景,配置成本高
protobuf
// User.proto
syntax = "proto3";
message User {
    string name = 1;
    int32 age = 2;
    string password = 3;
}
java
// 序列化
UserProto.User.Builder builder = UserProto.User.newBuilder();
builder.setName("张三");
builder.setAge(25);
byte[] bytes = builder.build().toByteArray();

// 反序列化
UserProto.User user = UserProto.User.parseFrom(bytes);

Kryo

优点

  • 二进制格式,体积小
  • 性能最快(无反射,直接序列化)
  • API 简洁

缺点

  • 不跨语言
  • 不同版本 Kryo 序列化结果不兼容
  • 需要注册类
java
Kryo kryo = new Kryo();
kryo.register(User.class);

// 序列化
Output output = new Output(new FileOutputStream("user.kryo"));
kryo.writeObject(output, user);
output.close();

// 反序列化
Input input = new Input(new FileInputStream("user.kryo"));
User u = kryo.readObject(input, User.class);
input.close();

性能对比

测试数据(来自网络综合测试,仅供参考):

方案序列化速度反序列化速度体积(相对值)
Java 原生最慢最慢100%
JSON较慢较慢300%
Kryo最快最快20%
Protobuf10%

(实际性能取决于数据结构和测试场景)

选型建议

┌─────────────────────────────────────────────────────────────────┐
│  选型口诀:                                                       │
│                                                                 │
│  跨语言 + 接口定义严格  →  Protobuf                              │
│  跨语言 + 调试友好     →  JSON                                   │
│  高性能 + Java 专用    →  Kryo                                  │
│  简单对象 + 零依赖     →  Java 原生                             │
└─────────────────────────────────────────────────────────────────┘

典型应用场景

场景推荐方案
Redis 缓存Kryo / Java 原生
Dubbo RPCHessian / Dubbo 序列化
HTTP APIJSON
gRPCProtocol Buffers
Kafka 消息JSON / Avro
文件持久化Kryo / Java 原生

总结

  • 性能优先:Kryo(Java 专用)或 Protobuf(跨语言)
  • 跨语言通用:JSON 或 Protobuf
  • 零依赖:Java 原生序列化
  • 接口契约:Protobuf(.proto 即接口定义)

基于 VitePress 构建