- 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之外,所有值都相應地使用了預設值。