- Protocol Buffers 教程
- Protocol Buffers - 首页
- Protocol Buffers - 简介
- Protocol Buffers - 基本应用
- Protocol Buffers - 结构
- Protocol Buffers - message
- Protocol Buffers - 字符串
- Protocol Buffers - 数字
- Protocol Buffers - 布尔值
- Protocol Buffers - 枚举
- Protocol Buffers - 重复字段
- Protocol Buffers - map
- Protocol Buffers - 嵌套类
- Protocol Buffers - 可选字段与默认值
- Protocol Buffers - 语言无关性
- Protocol Buffers - 复合数据类型
- Protocol Buffers - 命令行使用
- Protocol Buffers - 更新定义规则
- Protocol Buffers - 与Kafka集成
- Protocol Buffers - 其他语言支持
- Protocol Buffers 有用资源
- Protocol Buffers - 快速指南
- Protocol Buffers - 有用资源
- Protocol Buffers - 讨论
Protocol Buffers - 可选字段与默认值
概述
我们已经了解了各种数据类型及其使用方法。如果在序列化时未指定值会发生什么?“proto2”版本支持“required”和“optional”标签,这有助于确定如果所需的解析逻辑不可用,序列化/反序列化是否应该失败。但是,“required”标签在“proto3”版本中已移除。失败部分需要由相应的代码处理。现在每个属性都是可选的,并具有默认值。因此,从“proto3”版本开始,“optional”的使用是多余的。
Protocol Buffers根据下表支持其数据类型的默认值:
| 数据类型 | 默认值 |
|---|---|
| Int32 / Int64 | 0 |
| Float/double | 0.0 |
| 字符串 | 空字符串 |
| 布尔值 | False |
| 枚举 | 第一个枚举项,即“index=0”的项 |
| 重复类型 | 空列表 |
| Map | 空Map |
| 嵌套类 | null |
因此,如果未为这些数据类型指定数据,则它们将采用上述默认值。现在,让我们继续我们的theater示例来演示其工作原理。
在这个例子中,我们将让所有字段使用默认值。唯一指定的字段将是剧院的名称。
继续我们来自Protocol Buffers - 字符串章节的theater示例,以下是我们需要使用的语法,以指示 Protobuf 我们将创建不同的数据类型:
theater.proto
syntax = "proto3";
package theater;
option java_package = "com.tutorialspoint.theater";
message Theater {
string name = 1;
string address = 2;
int32 total_capcity = 3;
int64 mobile = 4;
float base_ticket_price = 5;
bool drive_in = 6;
enum PAYMENT_SYSTEM {
CASH = 0;
CREDIT_CARD = 1;
DEBIT_CARD = 2;
APP = 3;
}
PAYMENT_SYSTEM payment = 7;
repeated string snacks = 8;
map<string, int32> movieTicketPrice = 9;
TheaterOwner owner = 10;
}
message TheaterOwner{
string name = 1;
string address = 2;
}
现在我们的message类包含多个属性。
从Proto文件创建Java类
要使用 Protobuf,我们现在必须使用protoc二进制文件从此“.proto”文件创建所需的类。让我们看看如何做到这一点:
protoc --java_out=. theater.proto
这将在当前目录的com > tutorialspoint > theater文件夹中创建一个TheaterOuterClass.java类。我们在应用程序中使用此类,类似于Protocol Buffers - 基本应用章节中所做的那样。
使用从Proto文件创建的Java类
TheaterWriter.java
package com.tutorialspoint.theater;
import java.io.FileOutputStream;
import java.io.IOException;
import com.tutorialspoint.theater.TheaterOuterClass.Theater;
public class TheaterWriter {
public static void main(String[] args) throws IOException {
Theater theater = Theater.newBuilder()
.setName("SilverScreen")
.build();
String filename = "theater_protobuf_output";
System.out.println("Saving theater information to file: " + filename);
try(FileOutputStream output = new FileOutputStream(filename)){
theater.writeTo(output);
}
System.out.println("Saved theater information with following data to disk: \n" + theater);
}
}
接下来,我们将有一个reader来读取theater信息:
TheaterReader.java
package com.tutorialspoint.theater;
import java.io.FileInputStream;
import java.io.IOException;
import com.tutorialspoint.theater.TheaterOuterClass.Theater;
import com.tutorialspoint.theater.TheaterOuterClass.Theater.Builder;
public class TheaterReader{
public static void main(String[] args) throws IOException {
Builder theaterBuilder = Theater.newBuilder();
String filename = "theater_protobuf_output";
System.out.println("Reading from file " + filename);
try(FileInputStream input = new FileInputStream(filename)) {
Theater theater = theaterBuilder.mergeFrom(input).build();
System.out.println(
"Name:" + theater.getName() + "\n" +
"Address:" + theater.getAddress() + "\n" +
"Drive_In:" + theater.getDriveIn() + "\n" +
"Total Capacity:" + theater.getTotalCapcity() + "\n" +
"Base Ticket Prices: " + theater.getBaseTicketPrice() + "\n" +
"Owner: " + theater.getOwner() + "\n" +
"Snacks: " + theater.getSnacksList() + "\n" +
"Payment: " + theater.getPayment()
);
//Map<FieldDescriptor, Object> f = theater.getAllFields();
System.out.println("List of fields explicitly specified: " + theater.getAllFields());
}
}
}
编译项目
现在我们已经设置了reader和writer,让我们编译项目。
mvn clean install
序列化Java对象
现在,编译后,让我们首先执行writer:
> java -cp .\target\protobuf-tutorial-1.0.jar com.tutorialspoint.theater.TheaterWriter Saving theater information to file: theater_protobuf_output Saved theater information with following data to disk: name: "SilverScreen"
反序列化序列化对象
现在,让我们执行reader从同一个文件读取:
java -cp .\target\protobuf-tutorial-1.0.jar com.tutorialspoint.theater.TheaterReader
Reading from file theater_protobuf_output
Name:SilverScreen
Address:
Drive_In:false
Total Capacity:0
Base Ticket Prices: 0.0
Owner:
Snacks: []
Payment: CASH
List of fields explicitly specified: {theater.Theater.name=SilverScreen}
因此,正如我们所看到的,除了我们明确指定为最后一行的name之外,所有值都相应地使用了默认值。