java protobuf
生成代码
protoc --java_out=\src\main\java ChatPacket.proto
解析二进制数据
使用 ChatPacket 生成和解析二进制数据的两个实例
下面是两个实例,展示如何使用 ChatPacket 类生成二进制数据并将其解析回 ChatPacket 对象。你可以将这些实例直接应用到你的 Java 项目中。
实例 1:生成二进制数据
在这个实例中,我们将创建一个 ChatPacket 对象并将其序列化为二进制数据(字节数组)。
代码示例
package com.litongjava.im.protobuf;
import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket;
import com.litongjava.im.protobuf.ChatPacketOuter.CommandType;
public class ChatPacketBinaryExample {
public static void main(String[] args) {
// 创建一个 ChatPacket 对象
ChatPacket chatPacket = ChatPacket.newBuilder().setCmd(CommandType.COMMAND_CHAT_REQ).
setSequence(1234567890L).
//
setFrom("user123").setTo("user456").setToken("abcdefg")
//
.setCreateTime(1725338896411L).build();
// 将 ChatPacket 对象序列化为二进制数据
byte[] binaryData = chatPacket.toByteArray();
// 输出二进制数据长度
System.out.println("Serialized binary data length: " + binaryData.length);
}
}
Serialized binary data length: 42
解释
ChatPacket.newBuilder():使用生成的ChatPacket类的 Builder 模式创建一个新的ChatPacket对象。.toByteArray():将ChatPacket对象序列化为字节数组(二进制数据)。- 输出:输出二进制数据的长度。
实例 2:解析二进制数据
这个实例展示了如何将二进制数据反序列化回 ChatPacket 对象。
代码示例
package com.litongjava.im.protobuf;
import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket;
import com.litongjava.im.protobuf.ChatPacketOuter.CommandType;
import com.google.protobuf.InvalidProtocolBufferException;
public class ChatPacketBinaryParsingExample {
public static void main(String[] args) {
// 创建一个 ChatPacket 对象
ChatPacket chatPacketFrom = ChatPacket.newBuilder().setCmd(CommandType.COMMAND_CHAT_REQ).setSequence(1234567890L).
//
setFrom("user123").setTo("user456").setToken("abcdefg")
//
.setCreateTime(1725338896411L).build();
// 将 ChatPacket 对象序列化为二进制数据
byte[] binaryData = chatPacketFrom.toByteArray();
try {
// 从二进制数据解析出 ChatPacket 对象
ChatPacket chatPacket = ChatPacket.parseFrom(binaryData);
// 输出解析后的 ChatPacket 对象
System.out.println("Parsed ChatPacket: ");
System.out.println("cmd: " + chatPacket.getCmd());
System.out.println("sequence: " + chatPacket.getSequence());
System.out.println("from: " + chatPacket.getFrom());
System.out.println("to: " + chatPacket.getTo());
System.out.println("token: " + chatPacket.getToken());
System.out.println("createTime: " + chatPacket.getCreateTime());
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
}
Parsed ChatPacket:
cmd: COMMAND_CHAT_REQ
sequence: 1234567890
from: user123
to: user456
token: abcdefg
createTime: 1725338896411
解释
ChatPacket.parseFrom(binaryData):使用parseFrom方法将字节数组反序列化为ChatPacket对象。- 错误处理:捕获
InvalidProtocolBufferException异常,该异常在二进制数据不符合ChatPacket格式时抛出。 - 输出:输出解析后的
ChatPacket对象的内容。
总结
- 生成二进制数据:通过调用
toByteArray()方法将ChatPacket对象序列化为字节数组。 - 解析二进制数据:通过调用
ChatPacket.parseFrom()方法将字节数组反序列化回ChatPacket对象。
通过这两个实例,你可以将 ChatPacket 对象与二进制数据互相转换,从而方便地在网络传输、数据存储等场景中使用 Protobuf 的高效序列化与反序列化特性。
生成 JSON 数据
使用 ChatPacket 生成 JSON 数据
要将 ChatPacket 对象转换为 JSON 字符串,可以使用 Protobuf 提供的 JsonFormat 类。下面是一个详细的示例,展示如何将 ChatPacket 对象序列化为 JSON 数据。
步骤:将 Protobuf 对象转换为 JSON 字符串
确保包含 Protobuf Java 库:确保项目中已经包含 Protobuf Java 运行时库和
protobuf-java-util工具库,因为JsonFormat类在protobuf-java-util库中。如果使用 Maven,添加以下依赖(假设你已经添加过了):
<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>4.28.0-RC2</version> <!-- 选择与您的 .proto 语法兼容的版本 --> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>4.28.0-RC2</version> </dependency>导入所需的类:
import com.google.protobuf.util.JsonFormat; import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket; import com.google.protobuf.InvalidProtocolBufferException;将
ChatPacket对象转换为 JSON 字符串:使用
JsonFormat.Printer类将ChatPacket对象转换为 JSON 字符串。public String convertChatPacketToJson(ChatPacket chatPacket) throws InvalidProtocolBufferException { // 使用 JsonFormat 创建 Printer JsonFormat.Printer printer = JsonFormat.printer().includingDefaultValueFields(); // 将 ChatPacket 对象转换为 JSON 字符串 return printer.print(chatPacket); }注意:
includingDefaultValueFields()方法可以在 JSON 中包括所有字段的默认值。
示例代码
以下是一个完整示例,展示如何将 ChatPacket 对象转换为 JSON 字符串。
Java 代码
package com.litongjava.im.protobuf;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.util.JsonFormat;
import com.litongjava.im.protobuf.ChatPacketOuter.ChatMessage;
import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket;
import com.litongjava.im.protobuf.ChatPacketOuter.CommandType;
import com.litongjava.im.protobuf.ChatPacketOuter.TextContent;
public class ChatPacketToJsonExample {
public static String convertChatPacketToJson(ChatPacket chatPacket) throws InvalidProtocolBufferException {
// 使用 JsonFormat 创建 Printer
JsonFormat.Printer printer = JsonFormat.printer();
// 将 ChatPacket 对象转换为 JSON 字符串
return printer.print(chatPacket);
}
public static void main(String[] args) {
// 创建一个 ChatPacket 对象
TextContent textContent = com.litongjava.im.protobuf.ChatPacketOuter.TextContent.newBuilder()
//
.setText("Hello, world!").build();
ChatMessage chatMessage = com.litongjava.im.protobuf.ChatPacketOuter.ChatMessage.newBuilder()
//
.setMsgType("text").setTextContent(textContent).build();
ChatPacket chatPacket = ChatPacket.newBuilder()
//
.setCmd(CommandType.COMMAND_CHAT_REQ)
//
.setSequence(1234567890L)
//
.setFrom("user123")
//
.setTo("user456")
//
.setToken("abcdefg")
//
.setCreateTime(1725338896411L)
//
.setChatMessage(chatMessage).build();
try {
// 将 ChatPacket 对象转换为 JSON 字符串
String jsonString = convertChatPacketToJson(chatPacket);
System.out.println("Generated JSON data: " + jsonString);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
}
输出
运行上述代码,输出将类似于以下 JSON 字符串:
{
"cmd": "COMMAND_CHAT_REQ",
"sequence": "1234567890",
"from": "user123",
"to": "user456",
"createTime": "1725338896411",
"token": "abcdefg",
"chatMessage": {
"msgType": "text",
"textContent": {
"text": "Hello, world!"
}
}
}
解释
JsonFormat.printer():使用JsonFormat的printer()方法创建一个 JSON 打印器。printer.print(chatPacket):将ChatPacket对象序列化为 JSON 字符串。
总结
通过使用 Protobuf 提供的 JsonFormat 工具类,可以方便地将 ChatPacket 对象转换为 JSON 字符串。这有助于在客户端和服务器之间进行数据交换时,保持数据的可读性和可移植性。
解析 JSON 数据
在 Java 应用中,当从客户端接收到 JSON 字符串时,可以利用 Protobuf 提供的内置 JSON 解析功能,将其转换为由 .proto 文件生成的 ChatPacketOuter.ChatPacket 类的实例。Protobuf 提供了 JsonFormat 类,可以方便地实现 JSON 与 Protobuf 对象之间的转换。
使用 Protobuf 的 JsonFormat 将 JSON 字符串解析为 ChatPacket 对象
以下是实现这一转换的步骤以及示例代码。
步骤:将 JSON 字符串解析为 Protobuf 对象
确保包含 Protobuf Java 库:首先需要在项目中添加 Protobuf Java 运行时库。
如果使用 Maven,可以添加以下依赖:<dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>4.28.0-RC2</version> <!-- 选择与您的 .proto 语法兼容的版本 --> </dependency> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>4.28.0-RC2</version> </dependency>导入所需的类:
import com.google.protobuf.util.JsonFormat; import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket; import com.google.protobuf.InvalidProtocolBufferException;解析 JSON 字符串为 Protobuf 对象:
使用JsonFormat.Parser类将 JSON 字符串解析为ChatPacket对象。public ChatPacket parseJsonToChatPacket(String jsonString) throws InvalidProtocolBufferException { ChatPacket.Builder builder = ChatPacket.newBuilder(); JsonFormat.Parser parser = JsonFormat.parser().ignoringUnknownFields(); parser.merge(jsonString, builder); return builder.build(); }注意:使用
ignoringUnknownFields()方法可以忽略 JSON 中与 Protobuf 不匹配的字段。
示例代码
以下是一个完整示例,展示如何将 JSON 字符串转换为 ChatPacket 对象。
示例 JSON 字符串
{
"cmd": 11,
"sequence": 1234567890,
"from": "user123",
"to": "user456",
"token": "abcdefg",
"createTime": 1725338896411,
"body": {
"msgType": "text",
"textContent": {
"text": "Hello, world!"
}
}
}
Java 代码
package com.litongjava.im.protobuf;
import com.google.protobuf.util.JsonFormat;
import com.litongjava.im.protobuf.ChatPacketOuter.ChatPacket;
import com.google.protobuf.InvalidProtocolBufferException;
public class ChatPacketParser {
public static ChatPacket parseJsonToChatPacket(String jsonString) throws InvalidProtocolBufferException {
// 创建 ChatPacket 的 builder
ChatPacket.Builder builder = ChatPacket.newBuilder();
// 创建 JsonFormat 解析器
JsonFormat.Parser parser = JsonFormat.parser().ignoringUnknownFields();
// 将 JSON 字符串解析到 builder 中
parser.merge(jsonString, builder);
// 构建 ChatPacket 对象
return builder.build();
}
public static void main(String[] args) {
String jsonString = "{\n" +
" \"cmd\": 11,\n" +
" \"sequence\": 1234567890,\n" +
" \"from\": \"user123\",\n" +
" \"to\": \"user456\",\n" +
" \"token\": \"abcdefg\",\n" +
" \"createTime\": 1725338896411,\n" +
" \"body\": {\n" +
" \"msgType\": \"text\",\n" +
" \"textContent\": {\n" +
" \"text\": \"Hello, world!\"\n" +
" }\n" +
" }\n" +
"}";
try {
ChatPacket chatPacket = parseJsonToChatPacket(jsonString);
System.out.println("Parsed ChatPacket: " + chatPacket);
} catch (InvalidProtocolBufferException e) {
e.printStackTrace();
}
}
}
解释
- Builder 模式:Protobuf 使用 Builder 模式来构建消息对象,因此首先要创建一个
ChatPacket.Builder实例。 - JsonFormat.Parser:创建一个解析器实例,并配置忽略未知字段。
- 解析:使用
parser.merge(jsonString, builder)方法将 JSON 字符串解析到 builder 中。 - 构建对象:通过
builder.build()获得不可变的ChatPacket对象。
重要注意事项
- JSON 字段名称:JSON 字段名称必须与 Protobuf 字段名称匹配。Protobuf 会将字段名称转换为小驼峰命名法(lowerCamelCase)。
- Oneof 字段处理:
body在.proto文件中定义为oneof,因此在 JSON 中body字段下只能存在一种消息类型。 - 枚举:在 Protobuf 中,枚举可以通过名称或整数值来指定。
- 错误处理:要处理
InvalidProtocolBufferException异常,如果 JSON 不符合 Protobuf 模式会抛出此异常。 - 未知字段:使用
ignoringUnknownFields()来忽略 JSON 中未在 Protobuf 消息中定义的字段。
解析不同消息类型的 JSON
如果 body 字段中包含不同类型的消息,如文本消息或图片消息,确保在 JSON 中正确指定 msgType 及相应的内容。例如,对于图片消息:
{
"cmd": 11,
"sequence": 1234567890,
"from": "user123",
"to": "user456",
"token": "abcdefg",
"createTime": 1725338896411,
"body": {
"msgType": "image",
"imageContent": {
"url": "http://example.com/image.png",
"width": 800,
"height": 600,
"format": "png"
}
}
}
结论
通过利用 Protobuf 的 JsonFormat 类,可以轻松地将 JSON 字符串解析为 Protobuf 对象。请确保 JSON 结构与 Protobuf 消息定义一致,尤其要注意字段名称和 oneof 字段。这样可以实现高效、类型安全的消息处理。
