protobuf 資料型別
protobuf作為支援多種程式語言的序列化庫,有豐富的資料型別。同時資料型別,既能獨立於各種程式語言內嵌的資料型別,又能與它們,對應和轉換。message複合型別是交換資料的單元。在message中,定義資料型別欄位,裝載資料。
標量資料型別
protobuf定義的標量資料型別,其對應於C++中的資料型別,名稱上基本相同。 int32->int32_t , int64->int64_t , string->string等。
protobuf的資料型別與C++,Java,Python和Go語言中的資料型別都有一一對應的關係。
複合型別
oneof型別
類似C語言的union。
message SampleMessage { oneof test_oneof { string name = 4; SubMessage sub_message = 9; }}
Map型別
類似STL的map。map型別不能巢狀定義。
map
不用map時,用下面的等價形式。
message MapFieldEntry { optional key_type key = 1; optional value_type value = 2;}repeated MapFieldEntry map_field = N;
RPC服務介面型別
。proto檔案中定義rpc service介面。
service SearchService { //rpc介面函式是Search //引數是SearchRequest,返回SearchResponse Search (SearchRequest) returns (SearchResponse);}
實現上述介面的client和server端舉例。
RPC client
using google::protobuf;protobuf::RpcChannel* channel;protobuf::RpcController* controller;SearchService* service;SearchRequest request;SearchResponse response;void DoSearch() { // You provide classes MyRpcChannel and MyRpcController, which implement // the abstract interfaces protobuf::RpcChannel and protobuf::RpcController。 channel = new MyRpcChannel(“somehost。example。com:1234”); controller = new MyRpcController; // The protocol compiler generates the SearchService class based on the // definition given above。 service = new SearchService::Stub(channel); // Set up the request。 request。set_query(“protocol buffers”); // Execute the RPC。 service->Search(controller, request, response, protobuf::NewCallback(&Done));}void Done() { delete service; delete channel; delete controller;}
RPC Server。
using google::protobuf;class ExampleSearchService : public SearchService { public: void Search(protobuf::RpcController* controller, const SearchRequest* request, SearchResponse* response, protobuf::Closure* done) { if (request->query() == “google”) { response->add_result()->set_url(“http://www。google。com”); } else if (request->query() == “protocol buffers”) { response->add_result()->set_url(“http://protobuf。googlecode。com”); } done->Run(); }};int main() { // You provide class MyRpcServer。 It does not have to implement any // particular interface; this is just an example。 MyRpcServer server; protobuf::Service* service = new ExampleSearchService; server。ExportOnPort(1234, service); server。Run(); delete service; return 0;}
proto3新增的資料型別
標量資料型別支援更多的語言,增加支援Ruby,C#,PHP和Dart。
protobuf <-> JSON 定義 type-by-type對應關係。這是proto3最實用的特性了。
如果JSON編碼資料中缺少某個值,或者其值為null,則在解析為protobuf時,它將被解釋為相應的預設值。
如果欄位在protobuf中具有預設值,則預設情況下將在JSON編碼的資料中省略該欄位以節省空間。
Any資料型別(開發中的功能)
類似C++中的泛型。
import “google/protobuf/any。proto”;message ErrorStatus { string message = 1; repeated google。protobuf。Any details = 2;}
proto3新增的特性
欄位定義無需再加required 和 optional。
message SearchRequest { string query = 1; int32 page_number = 2; int32 result_per_page = 3;}
enum型別必須定義0值
“every enum definition must contain a constant that maps to zero as its first element。”
雜項
訊息巢狀定義和巢狀使用
類似C語言結構體巢狀。
訊息擴充套件
欄位佔位符,給未來使用。實際是沒有定義這些欄位。
message Foo { extensions 100 to 199;}
在欄位序號126上定義一個欄位。
extend Foo { optional int32 bar = 126;}
使用擴充套件欄位。
Foo foo;foo。SetExtension(bar, 15);
package
定義名稱空間。
package foo。bar;message Open { 。。。 }
引用定義過的包。
message Foo { 。。。 foo。bar。Open open = 1; 。。。}
C++產生的名稱空間:
foo::bar
。
引用其它.proto檔案
在。proto的開頭使用import。
import “myproject/other_protos。proto”;
生成程式碼
protoc ——proto_path=IMPORT_PATH ——cpp_out=DST_DIR ——java_out=DST_DIR ——python_out=DST_DIR path/to/file。proto
多條訊息的流式化
protobuf的二進位制格式不能自我界定。protobuf不能確定訊息的二進位制邊界。同時輸出多個訊息時,要自己定義訊息的邊界。一種方法,將訊息的位元組大小先寫出,然後再寫出訊息本身。
不支援大資料集
但是用protobuf作為大資料集中的部分。
訊息不能自描述
原始的訊息,如果沒有proto檔案,是無法解析的。