使用 protobuf-java-util 实现 Protobuf 与 JSON 的无缝转换
常见技术问题 刘宇帅 6天前 阅读量: 20
在实际开发中,我们常常需要在 REST 接口(使用 JSON)与 gRPC 服务(使用 Protobuf)之间做数据转换。Google 提供的 protobuf-java-util
库,就是为了解决这个痛点而生的。它极大地简化了 Protobuf 对象与 JSON 之间的序列化与反序列化工作。
本文将介绍 protobuf-java-util
的核心功能、常见使用场景、并提供完整示例,帮助你在项目中快速上手。
一、什么是 protobuf-java-util
protobuf-java-util
是 Google 官方提供的一个 Protobuf 辅助工具库,主要功能包括:
- ✅ Protobuf ↔ JSON 的互转
- ✅ 支持 Timestamp、Any、Wrapper 类型的自动转换
- ✅ 提供格式化选项(压缩、默认值输出等)
适用于任何由 protoc
编译生成的 Java Protobuf 类,也与 gRPC 生成的类完全兼容。
二、依赖引入
在 Maven 项目中添加如下依赖:
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java-util</artifactId>
<version>3.11.0</version>
</dependency>
⚠️ 注意:
protobuf-java-util
依赖于protobuf-java
,无需手动再引入。
三、核心类与功能
1. JsonFormat.printer()
将 Protobuf 对象转换为 JSON 字符串:
String json = JsonFormat.printer().print(protoObject);
可选配置:
.includingDefaultValueFields()
:输出所有字段,即使是默认值.omittingInsignificantWhitespace()
:压缩 JSON,无缩进空格.preservingProtoFieldNames()
:使用 Protobuf 字段名(默认使用驼峰)
2. JsonFormat.parser()
将 JSON 字符串反序列化为 Protobuf 对象:
YourMessage.Builder builder = YourMessage.newBuilder();
JsonFormat.parser().merge(jsonString, builder);
YourMessage message = builder.build();
四、使用示例
示例:定义一个简单的消息
// user.proto
syntax = "proto3";
message User {
string name = 1;
int32 age = 2;
}
使用 protoc
编译生成 User.java
,我们可以这样完成 JSON 与 Protobuf 的互转:
import com.google.protobuf.util.JsonFormat;
String json = "{\"name\": \"Alice\", \"age\": 30}";
// JSON → Protobuf
User.Builder builder = User.newBuilder();
JsonFormat.parser().merge(json, builder);
User user = builder.build();
// Protobuf → JSON
String outputJson = JsonFormat.printer()
.includingDefaultValueFields()
.print(user);
System.out.println(outputJson);
输出结果:
{
"name": "Alice",
"age": 30
}
五、常见进阶用法
1. 支持 google.protobuf.Timestamp
如果你的消息中包含时间字段:
import "google/protobuf/timestamp.proto";
message Event {
string title = 1;
google.protobuf.Timestamp created_at = 2;
}
转换时会自动识别 ISO8601 格式时间:
{
"title": "Launch",
"createdAt": "2024-05-13T12:00:00Z"
}
无需额外处理,protobuf-java-util
会自动完成 Timestamp 与时间字符串之间的转换。
2. 支持 google.protobuf.Any
Any
类型字段可以嵌套任意消息,protobuf-java-util
也能识别:
import "google/protobuf/any.proto";
message Wrapper {
google.protobuf.Any payload = 1;
}
在 JSON 中表现为:
{
"payload": {
"@type": "type.googleapis.com/your.package.User",
"name": "Alice",
"age": 25
}
}
六、使用建议与注意事项
建议 / 限制 | 说明 |
---|---|
✅ 可与 REST API 搭配使用 | 可用于 Spring Boot 接收 JSON,转为 gRPC 参数 |
✅ 自动处理嵌套消息 | 嵌套对象可完整转换,无需手动处理 |
❌ 不支持 Jackson/Gson 注解 | 与常规 JSON 序列化工具无兼容性 |
⚠️ Builder 模式必须使用 | merge() 只能用于 Protobuf 的 Builder ,不是 Message |
七、典型应用场景
- ? 网关服务接收 JSON → 转换为 Protobuf → 调用 gRPC
- ? 日志记录 gRPC 返回的 Protobuf → 转换为 JSON 存储
- ? 第三方 API 返回 JSON → 合并为 Protobuf 对象发往服务层
八、总结
protobuf-java-util
是连接 JSON 与 Protobuf 的高效桥梁。它帮助我们轻松完成数据格式转换,特别适用于 gRPC 与 REST 混用架构,在现代微服务场景中非常实用。
无论你是做服务对接、数据转换、还是开发调试,掌握这个工具都能大大提升开发效率。