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<key_type, value_type> map_field = N;
不用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文件,是无法解析的。
本文暂时没有评论,来添加一个吧(●'◡'●)