protobuf支持的數據類型,protobuf string類型_Protobuf 語言指南(proto3)

 2023-12-06 阅读 21 评论 0

摘要:定義消息類型首先讓我們看一個非常簡單的例子. 假設要定義搜索請求消息格式, 其中每個搜索請求都有一個查詢字符串, 您感興趣的特定結果頁面以及每頁的一些結果. 這是用于定義消息類型的 .proto 文件.syntax = "proto3";message SearchRequest {string query =

定義消息類型

首先讓我們看一個非常簡單的例子. 假設要定義搜索請求消息格式, 其中每個搜索請求都有一個查詢字符串, 您感興趣的特定結果頁面以及每頁的一些結果. 這是用于定義消息類型的 .proto 文件.

syntax = "proto3";

message SearchRequest {

string query = 1;

protobuf支持的數據類型?int32 page_number = 2;

int32 result_per_page = 3;

}

注意以下幾點:

該文件的第一行指定使用 proto3 語法; 如果不寫則使用 proto2.

一個消息對應一個字段, 一個字段對應一個數據類型.

json和protobuf的區別?值得注意的是: 字段類型可以是枚舉或其他數據類型.

字段編號

比如 string query = 1; 字段, 1 就是字段編號(unique number).

字段編號的范圍為 1 到 536,870,911. 不能使用數字 19000 到 19999, 因為它們是為 Google Protobuf 保留的.

在同一個 .proto 文件中添加多個消息類型

message SearchRequest {

c語言string函數用法,string query = 1;

int32 page_number = 2;

int32 result_per_page = 3;

}

message SearchResponse {

...

prototype和__proto__,}

保留字段

當定義好字段后, 在后續開發中發現某個字段根本沒用.

例如 string userName = 2; 字段, 這個時候最好不要進行注釋或刪除.

有可能以后加載相同的舊版本, 這可能會導致數據損壞, 隱私錯誤等. 確保不會發生這種情況的一種方法是指定要刪除的字段為保留字段.

message SubscribeReq {

json轉protobuf。reserved 2;

int32 subReqID = 1;

string userName = 2;

string productName = 3;

string address = 4;

}

c語言string函數有哪些、顧名思義, 就是此字段會被保留可能在以后會使用此字段. 使用關鍵字 reserved 表示要保留字段編號為 2.

上面代碼我們在生成 Java 文件的時候會出現 ubscribeReqPeoro.proto: Field "userName" uses reserved number 2 錯誤信息, 所以需要將 string userName = 2; 注釋, 或者刪除.

值得注意的是: 您不能在同一 reserved 語句中混合字段名稱和字段編號. 下面是表準格式:

message Foo {

reserved 2, 15, 9 to 11;

reserved "foo", "bar";

c語言string類型輸入、}

指定字段規則

所指定的消息字段修飾符必須是如下之一:

singular: 一個格式良好的消息應該有0個或者1個這種字段 (但是不能超過1個).

repeated: 一個格式良好的消息中, 這種字段可以重復任意多次 (包括 0 次). 重復值的順序會被保留.

枚舉

python protobuf解析。當需要定義一個消息類型的時候, 可能想為一個字段指定某 “預定義值序列” 中的一個值.

例如, 假設要為每一個 SearchRequest 消息添加一個 corpus 字段, 而 corpus 的值可能是 UNIVERSAL, WEB, IMAGES, LOCAL, NEWS, PRODUCTS 或 VIDEO 中的一個.

其實可以很容易地實現這一點: 通過向消息定義中添加一個枚舉 (enum) 并且為每個可能的值定義一個常量就可以了.

在下面的例子中, 在消息格式中添加了一個叫做 Corpus 的枚舉類型——它含有所有可能的值——以及一個類型為 Corpus 的字段:

message SearchRequest {

string query = 1;

c語言string頭文件?int32 page_number = 2;

int32 result_per_page = 3;

enum Corpus {

UNIVERSAL = 0;

WEB = 1;

IMAGES = 2;

LOCAL = 3;

NEWS = 4;

PRODUCTS = 5;

VIDEO = 6;

}

Corpus corpus = 4;

}

值得注意的是:

每個枚舉類型必須將其第一個類型映射為 0, 這是因為:

必須有有一個 0 值, 我們可以用這個 0 值作為默認值.

這個零值必須為第一個元素, 為了兼容 proto2 語義, 枚舉類的第一個值總是默認值.

另外, 枚舉常量必須在 32 位整數范圍內, 并且盡量不要使用負數.

你可以通過將不同的枚舉常量指定為相同的值. 如果這樣做你需要將 allow_alias 設置為 true.

enum EnumAllowingAlias {

option allow_alias = true;

UNKNOWN = 0;

STARTED = 1;

RUNNING = 1;

}

enum EnumNotAllowingAlias {

UNKNOWN = 0;

STARTED = 1;

// RUNNING = 1; // Uncommenting this line will cause a compile error inside Google and a warning message outside.

}

其它消息類型

你可以將其他消息類型用作字段類型. 例如, 假設在每一個 SearchResponse 消息中包含 Result 消息, 此時可以在相同的 .proto 文件中定義一個 Result 消息類型, 然后在 SearchResponse 消息中指定一個 Result 類型的字段, 如:

message SearchResponse {

repeated Result results = 1;

}

message Result {

string url = 1;

string title = 2;

repeated string snippets = 3;

}

嵌套類型

你可以在其他消息類型中定義、使用消息類型, 在下面的例子中, Result 消息就定義在 SearchResponse 消息內, 如:

message SearchResponse {

message Result {

string url = 1;

string title = 2;

repeated string snippets = 3;

}

repeated Result results = 1;

}

如果你想在它的父消息類型的外部重用這個消息類型, 你需要以 Parent.Type 的形式使用它, 如:

message SomeOtherMessage {

SearchResponse.Result result = 1;

}

當然, 你也可以將消息嵌套任意多層, 如:

message Outer { // Level 0

message MiddleAA { // Level 1

message Inner { // Level 2

int64 ival = 1;

bool booly = 2;

}

}

message MiddleBB { // Level 1

message Inner { // Level 2

int32 ival = 1;

bool booly = 2;

}

}

}

導入定義

在上面的示例中, Result 和 SearchResponse 消息類型在同一文件中的, 如果要用作字段類型的消息類型在另一個 .proto 文件中定義, 該怎么辦?

可以 .proto 通過導入來使用其他文件中的定義. 需要在文件頂部添加 import 語句:

import "myproject/other_protos.proto";

默認情況下, 使用直接導入的 .proto 文件中的定義.

但是, 有時可能需要將 .proto 文件移動到新位置. 如果直接移動文件位置可能要修改許多代碼位置.

我們可以使用 import public 來解決這個問題.

實例代碼:

// new.proto

// All definitions are moved here

// old.proto

//This is the proto that all clients are importing.

import public“new.proto”;

import“other.proto”;

// client.proto

import "old.proto";

//您使用old.proto和new.proto中的定義,但不使用other.proto

Maps

如果要在數據定義中創建關聯映射, 協議緩沖區提供了一種方便的快捷方式語法:

map < key_type ,value_type > map_field = N ;

key_type 可以是任何整數或字符串類型.

value_type 可以是除了 map 的其他類型.

例如, 如果要創建項目映射, 其中每條 Project 消息都與字符串鍵相關聯, 則可以像下面這樣定義它:

map < string,Project > projects = 3;

值得注意的是: map 不能使用 repeated.

您可以向 .proto 文件添加 package 可選說明符, 以防止協議消息類型之間的名稱沖突.

package foo.bar;

message Open { ... }

然后, 您可以在定義消息類型的字段時使用包說明符:

message Foo {

...

foo.bar.Open open = 1;

...

}

Any (任意類型)

// new.proto

syntax = "proto3";

import "google/protobuf/any.proto";

message SearchRequest {

string query = 1;

int32 page_number = 2;

repeated google.protobuf.Any result_per_page = 3;

}

編譯的時候需要將 google/protobuf/any.proto 和 new.proto 文件放到一起. 要注意目錄結構.

然后執行下面命令進行編譯:

sudo ./protoc -I=/home/sc-ik/桌面/ --java_out=./java /home/sc-ik/桌面/*.proto

在對 result_per_page 進行賦值時, 需要用到 Any 類中的 public static Any pack(T message) 方法.

在 java 代碼中, 先創建 SearchRequest 對象, 然后對其他兩個屬性進行賦值.

New.SearchRequest.Builder searchRequest = New.SearchRequest.newBuilder();

searchRequest.setQuery("test");

searchRequest.setPageNumber(10086);

在對 result_per_page 進行賦值時, 需要注意: pack 方法的參數類型為 com.google.protobuf.Message 接口.

生成的 java 代碼中, 類是繼承自 GeneratedMessageV3.

public static final class SearchRequest extends

com.google.protobuf.GeneratedMessageV3 implements

// @@protoc_insertion_point(message_implements:SearchRequest)

SearchRequestOrBuilder {

private static final long serialVersionUID = 0L;

但是如果將result_per_page 賦值為 SearchRequest, 應該怎么操作呢?

重點就是繼承的 GeneratedMessageV3 抽象類, 這個抽象類又繼承了 AbstractMessage 抽象類, 而 AbstractMessage 抽象類就是 com.google.protobuf.Message 接口的實現.

public abstract class AbstractMessage

// TODO(dweis): Update GeneratedMessage to parameterize with MessageType and BuilderType.

extends AbstractMessageLite implements Message {

所以我們可以使用以下方法進行賦值.

searchRequest.addResultPerPage(

com.google.protobuf.Any.pack(

searchRequest.build()

)

);

pack() 方法我個人理解為序列化, 那么和他對應的是反序列化 unpack().

// 將接收到的字節數組飯序列化.

New.SearchRequest.Builder builder2 = New.SearchRequest.newBuilder().mergeFrom(bytes1);

// 獲取到 result_per_page 字段的值.

Any.Builder resultPerPageBuilder = builder2.getResultPerPageBuilder(0);

// 然后使用 unpack 將任意類型 進行反序列化, 得到想要的數據.

New.SearchRequest unpack1 = resultPerPageBuilder.build().unpack(New.SearchRequest.class);

編譯

編譯命令:

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/*.proto

如下:

sudo ./protoc -I=/home/sc-ik/桌面/ --java_out=./java /home/sc-ik/桌面/*.proto

版权声明:本站所有资料均为网友推荐收集整理而来,仅供学习和研究交流使用。

原文链接:https://hbdhgg.com/3/189012.html

发表评论:

本站为非赢利网站,部分文章来源或改编自互联网及其他公众平台,主要目的在于分享信息,版权归原作者所有,内容仅供读者参考,如有侵权请联系我们删除!

Copyright © 2022 匯編語言學習筆記 Inc. 保留所有权利。

底部版权信息