`
zuoshu
  • 浏览: 194815 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类
最新评论

【转】Protocol Buffers - Google's data interchange format

阅读更多

http://code.google.com/p/protobuf/

Protocol Buffers are a way of encoding structured data in an efficient yet extensible format. Google uses Protocol Buffers for almost all of its internal RPC protocols and file formats.

 

  • Options

http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/proto.html#options

 

1. java_package (file option): The package you want to use for your generated Java classes.

Proto代码  收藏代码
  1. option java_package = "com.example.foo";  

2. java_outer_classname (file option): The class name for the outermost Java class (and hence the file name) you want to generate.

Proto代码  收藏代码
  1. option java_outer_classname = "Ponycopter";  

3. optimize_for (file option): Can be set to SPEED , CODE_SIZE , or LITE_RUNTIME .

Proto代码  收藏代码
  1. option optimize_for = CODE_SIZE;  

 

http://code.google.com/intl/zh-CN/apis/protocolbuffers/docs/reference/java-generated.html

 

  • 根据反编译后的Java文件推导出proto文件

首先看看下面的proto文件生成的Java文件是什么样子的:

Proto代码  收藏代码
  1. package tutorial;  
  2.   
  3. option optimize_for = LITE_RUNTIME;  
  4. option java_package = "com.example.tutorial";  
  5. option java_outer_classname = "AddressBookProtos";  
  6.   
  7. message Person {  
  8.   required string name = 1;  
  9.   required int32 id = 2;  
  10.   optional string email = 3;  
  11.     
  12.   
  13.   enum PhoneType {  
  14.     MOBILE = 0;  
  15.     HOME = 1;  
  16.     WORK = 2;  
  17.   }  
  18.   
  19.   message PhoneNumber {  
  20.     required string number = 1;  
  21.     optional PhoneType type = 2 [default = HOME];  
  22.   }  
  23.   
  24.   repeated PhoneNumber phone = 4;  
  25.   optional bytes addressBytes = 6;  
  26. }  
  27.   
  28. message AddressBook {  
  29.   repeated Person person = 1;  
  30. }  

 

 

枚举类型会生成Java中的枚举:

Java代码  收藏代码
  1. public enum PhoneType  
  2.         implements com.google.protobuf.Internal.EnumLite {  
  3.       MOBILE(00),  
  4.       HOME(11),  
  5.       WORK(22),  
  6.       ;  
  7.         
  8.       public static final int MOBILE_VALUE = 0;  
  9.       public static final int HOME_VALUE = 1;  
  10.       public static final int WORK_VALUE = 2;  
  11.       ...  
  12. }  

 注意同时会生成一个以_VALUE作为后缀的常量。

 

下面的三个域生成的Java代码是什么样子呢?

required string name = 1;
required int32 id = 2;
optional string email = 3;

 

首先生成一个接口PersonOrBuilder,有下面的方法:

Java代码  收藏代码
  1. boolean hasName();  
  2. String getName();  
  3.   
  4. boolean hasId();  
  5. int getId();  
  6.   
  7. boolean hasEmail();  
  8. String getEmail();  

然后生成Person类,实现接口PersonOrBuilder,同时,定义了下面的常量:

Java代码  收藏代码
  1. public static final int NAME_FIELD_NUMBER = 1;  
  2. public static final int ID_FIELD_NUMBER = 2;  
  3. public static final int EMAIL_FIELD_NUMBER = 3;  

 可以看出,都有_FIELD_NUMBER后缀。

 

可以从isInitialized()函数中看判断某个域是optional还是required。optional的域不会在isInitialized()中进行检查。

Java代码  收藏代码
  1. public final boolean isInitialized() {  
  2.         if (!hasName()) {  
  3.             
  4.           return false;  
  5.         }  
  6.         if (!hasId()) {  
  7.             
  8.           return false;  
  9.         }  
  10.         ...  
  11. }  

 

对于域是一个message而不是原始类型的情况,判断是optional还是required有些区别:

比如,对于如下的proto:

Proto代码  收藏代码
  1. optional PhoneNumber mobile = 7;  
  2. required PhoneNumber cell = 8;  

 对于的Java代码为:

Java代码  收藏代码
  1. if (!hasCell()) {  
  2.   memoizedIsInitialized = 0;  
  3.   return false;  
  4. }  
  5. if (hasMobile()) {  
  6.   if (!getMobile().isInitialized()) {  
  7.     memoizedIsInitialized = 0;  
  8.     return false;  
  9.   }  
  10. }  
  11. if (!getCell().isInitialized()) {  
  12.   memoizedIsInitialized = 0;  
  13.   return false;  
  14. }  

 对于required message field, Java代码中会首先用一个if语句块hasXxx()判断,然后再用一个if语句块getXxx().isInitialized()进行判断,而对于optional message field,两个if语句块会嵌套一起。

 

在initFields()函数中查看具体有哪些fields,再结合XXX_FIELD_NUMBER一起分析。

 

判断extensions:

查看registerAllExtensions()函数。

通常是使用nested extensions,需要好好理解,其实很简单,只是写法有点绕:

http://code.google.com/apis/protocolbuffers/docs/proto.html#extensions
http://code.google.com/apis/protocolbuffers/docs/reference/java-generated.html#extension

 

下面的例子:

Java代码  收藏代码
  1. public static final int MAN_FIELD_NUMBER = 123;  
  2.     public static final  
  3.       com.google.protobuf.GeneratedMessageLite.GeneratedExtension<  
  4.         com.example.tutorial.AddressBookProtos.Person,  
  5.         com.example.tutorial.AddressBookProtos.Man> man = com.google.protobuf.GeneratedMessageLite  
  6.             .newSingularGeneratedExtension(  
  7.           com.example.tutorial.AddressBookProtos.Person.getDefaultInstance(),  
  8.           com.example.tutorial.AddressBookProtos.Man.getDefaultInstance(),  
  9.           com.example.tutorial.AddressBookProtos.Man.getDefaultInstance(),  
  10.           null,  
  11.           123,  
  12.           com.google.protobuf.WireFormat.FieldType.MESSAGE);  
  13.   }  

 可以得知Man是Person的extension,并且field number是123.

 

LazyStringList对应 repeat string xxx = 1;

this change coming up in 2.4.0: 
"""Added lazy conversion of UTF-8 encoded strings to String objects to improve 
performance."""

 

原文http://mysuperbaby.iteye.com/blog/1455286

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics