proto2语法
proto文件
protobuf的定義是通過proto文件進行定義的,一個標準的類型如下:
message SearchRequest {required string query = 1;optional int32 page_number = 2 [default = 10];optional int32 result_per_page = 3; }其中message定義了類型名字,其中每一個字段有三個選項:
- required:字段必填。
- optional: 字段選填,不填就會使用默認值,默認數值類型的默認值為0,string類型為空字符串,枚舉類型為第一個枚舉值。
- repeated: 數組類型,可以放入多個類型實例。
之后需要跟上數據類型,在類型之后為字段名。最后跟上“=N”這里N是標記位,每個字段都有標記位,各個字段不能重復且必須為正值,其最大值為 2^29 - 1,同時protobuf內部預留了19000到19999不能被用戶使用,官方建議將常用的字段放在前面,由于這個字段的大小隨著數值大小增加,如1-16只占用一個字節。最后可以跟上自定義的默認值。
在一個proto文件中可以存放多個message,message內部也可以定義message,外部如需調用需要指明對應的層級關系。同時可以使用import引入外部的proto文件:
還可以在proto文件中各個級別增加部分編譯設置,常用包括:
- java_package:生成的java包名
- java_outer_classname :生成的java類名
- optimize_for:設置編譯優化級別,SPEED-默認值速度優先,CODE_SIZE-最小代碼量,LITE_RUNTIME-最小運行時占用(適用于環境受限的情況)
數據類型
基礎數據類型
protobuf支持大多數基礎數據類型,下表包含常用類型,詳細列表見官方文檔
| double | double | |
| float | float | |
| int32 | int | 有符號整形建議使用sint32 |
| uint32 | int | 無符號整形 |
| sint32 | int | 有符號整形 |
| int64 | long | 有符號長整形建議使用sint64 |
| uint64 | long | 無符號長整形 |
| sint64 | long | 有符號長整形 |
| bool | boolean | |
| string | String | |
| byte | ByteString |
枚舉類型
protobuf可以定義枚舉類型:
enum EnumType {TYPEA = 0;TYPEB = 1;TYPEC = 2; }enum的每行字段都是一個枚舉值,等號后面跟的是實際值,默認實際值是不能一樣的,但只需要增加一個option配置就可以設置一樣的值:
enum EnumType {option allow_alias = true;TYPEA = 0;TYPEB = 0;TYPEC = 2; }自定義數據類型
還有就是自定義的message類型:
message MessageType {repeated string str = 1; }message CompositeType {optional MessageType message = 1; }oneof
oneof是一種特殊類型可以綁定一組變量,但是只有最后設置的那個變量才生效,之前的變量都會被清除:
-------proto------ message Foo {oneof test_oneof {string name = 1;int32 id = 2;} } -------java------- System.out.println(Demo.Foo.newBuilder().setId(1).setName("name").build().toString()); System.out.println(">>>"); System.out.println(Demo.Foo.newBuilder().setName("name").setId(1).build().toString()); -------輸出------- name: "name" >>> id: 1map
map類型可以接受鍵值對,鍵可以使用string或數值類型,值可以使用任意類型:
-------proto------ message Foo {map<string, string> bar = 1; } -------java------- Demo.Foo foo=Demo.Foo.newBuilder().putBar("key1","value1").putBar("key2","value2").build();FileOutputStream fos=new FileOutputStream("D://person"); foo.writeTo(fos); fos.close();FileInputStream fis=new FileInputStream("D://person"); Demo.Foo foo2=Demo.Foo.parseFrom(fis); System.out.println(foo2.getBarCount()); fis.close();extension
Extension有點類似繼承,可以向message對象內增加額外的字段:
message Foo {// ...extensions 100 to 199; //首先需要定義100-199為extension字段 }extend Foo {optional int32 bar = 100; //增加bar字段 }在使用extension時和普通字段有些不同,Java中如下:
public static void main(String[] args) throws IOException, ClassNotFoundException {//通過setExtension設置字段值Demo.Foo foo=Demo.Foo.newBuilder().setExtension(Demo.bar,1).build();//通過getExtension可以取值System.out.println(foo.getExtension(Demo.bar));FileOutputStream fos=new FileOutputStream("D://person");foo.writeTo(fos);fos.close();FileInputStream fis=new FileInputStream("D://person");//反序列化時需要注冊對應的extension字段,不然無法取到extesion的值ExtensionRegistry registry = ExtensionRegistry.newInstance();registry.add(Demo.bar);Demo.Foo foo2=Demo.Foo.parseFrom(fis,registry);System.out.println(foo2.getExtension(Demo.bar));fis.close(); }轉載于:https://www.cnblogs.com/resentment/p/6539021.html
總結
- 上一篇: 2017-03-10Git版本回退
- 下一篇: App Store 排名获取。