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());
      }
   }
}

編譯專案

現在我們已經設定了readerwriter,讓我們編譯專案。

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

廣告
© . All rights reserved.