使用 protobuf-java-util 实现 Protobuf 与 JSON 的无缝转换

常见技术问题

刘宇帅 1953 0 10月前

文章内容

在实际开发中,我们常常需要在 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 混用架构,在现代微服务场景中非常实用。

无论你是做服务对接、数据转换、还是开发调试,掌握这个工具都能大大提升开发效率。

专栏信息

常见技术问题
作者 刘宇帅
发布时间 10月前
阅读量 1953
评论数 0

摘要


暂无评论~

更多专栏文章

idea 提示 the file size exceeds the configured limit .Code insight features are not avaliable

在 IntelliJ IDEA 中,提示 “the file size exceeds the configured limit. Code insight features are not available” 表示当前文件的大小超出了 IDEA 的默认限制,因此无法启用代码自动提示、语法高亮等功能。默认文件大小限制为 2.5 MB。 解决方法 方

查看文章

ProxySQL详解

ProxySQL 是一个高性能、高可用性的 MySQL 代理,旨在为 MySQL 数据库提供负载均衡、读写分离、故障转移、查询缓存等高级功能。它通过在客户端和 MySQL 服务器之间充当中间层,实现对数据库连接和查询的智能管理,从而提升整体系统的性能和可靠性。

查看文章

git仓库迁移方法

迁移 Git 仓库是一个常见需求,尤其是在更换代码托管平台(如从 GitHub 迁移到 GitLab,或从本地仓库迁移到远程仓库)时。以下是几种常见的 Git 仓库迁移方法,具体使用哪种方法取决于你需要保留的内容(如历史记录、分支、

查看文章

Base64详解

Base64 是一种常用的编码方式,用于将二进制数据转换为ASCII字符,以便在文本环境中安全地传输和存储。由于许多传输媒介(如电子邮件、HTTP协议)对二进制数据有特定的限制或处理方式,Base64提供了一种可靠的方法来确保数据在这些环境中的完整性和可读性。

查看文章

Maven setting.xml 详解

一、什么是 settings.xml settings.xml 是 Maven 的配置文件,用于定义用户级别或全局的构建配置。它包含了对 Maven 构建过程影响较大的设置,如: 本地仓库的位置 远程仓库的镜像 代理服务器配置 认证信息(如私有仓库的用户名和

查看文章