每个.proto文件是以一个包声明开始的,这样防止名字冲突,然后以消息格式的方式定义数据如何组织。
这个.proto文件要被protoc编译器使用,会生成一个Java类,包含getter和setter方法,然后你可以使用这些方法进行序列化和反序列化对象。例如,下面的消息格式:
message User {
required string name = 1;
required int32 id = 2; // Id of the User
optional string email = 3; // Email of the User
}消息格式中值类型可以使用numbers,booleans,string,bytes,collections,enumerations,当然也开始嵌套其他消息类型,这样允许你层级式组织数据,类似于JSON一样。
消息格式中的Field可以配置为optional,required,repeated。
required表示初始化值必须被提供,否则field不能被初始化
optional表示如果没有初始化,那么默认的值被提供。
repeated表示该field可以出现多次(包含0次),而且值的顺序被保留。由于历史原因,如果是数值类型的重复fields不能进行 很好的编码。新的代码需要使用[packed=true]得到更好的性能。例如,
repeated int32 samples = 4[packed=true]可以使用//进行注释
使用protocol编译器可以生成对应语言的文件,例如,对于C++来说,每个.proto文件生成一个.h和.cc文件。
对Java来说,会为每个消息类型生成一个java文件,而且为创建消费类实例的构建类。对于其他语言来说,各有各的不同。
Java实例
message Person {
required string name = 1;
required int32 id = 2;
optional string email = 3;
enum phoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2[default=HOME];
}
repeated PhoneNumber phone = 4;
}
message AddressBook {
repeated Person person = 1;
}当包声明后,针对Java有两个特殊的选项,分别是:java_package和java_outer_classname,java_package配置你生成的类文件应该属于哪个包,如果你不配置,它仅仅对应包声明的包中。java_outer_classname定义一个类名,它包含文件中的所有类。如果你不配置java_outer_classname,那么将会使用转化后的文件名,例如,my_proto.proto文件会将MyProto作为类名。然后就可以开始定义消息格式。例如,Person,AddressBook。
编译Protocol文件
使用protoc编译器进行编译,生成对应语言的文件(c++,java,或者python),可以配置源目录,如果没有配置,那么当前目录被使用。
protoc -I=. --java_out=. tutorial.proto执行完成后,就会在当前目录下生成com/dufeng/protobuf/AddressBookProtos.java文件
在java文件中,对于每个field包含getters和setters方法。部分内容如下:
// Generated by the protocol buffer compiler. DO NOT EDIT!
// source: tutorial.proto
package com.dufeng.protobuf;
public final class AddressBookProtos {
private AddressBookProtos() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface PersonOrBuilder extends
// @@protoc_insertion_point(interface_extends:com.dufeng.Person)
com.google.protobuf.MessageOrBuilder {
/**
* <code>required string name = 1;</code>
* @return Whether the name field is set.
*/
boolean hasName();
/**
* <code>required string name = 1;</code>
* @return The name.
*/
java.lang.String getName();
/**
* <code>required string name = 1;</code>
* @return The bytes for name.
*/
com.google.protobuf.ByteString
getNameBytes();
/**
* <code>required int32 id = 2;</code>
* @return Whether the id field is set.
*/
boolean hasId();
/**
* <code>required int32 id = 2;</code>
* @return The id.
*/
int getId();
/**
* <code>optional string email = 3;</code>
* @return Whether the email field is set.
*/
boolean hasEmail();
/**
* <code>optional string email = 3;</code>
* @return The email.
*/
java.lang.String getEmail();
/**
* <code>optional string email = 3;</code>
* @return The bytes for email.
*/
com.google.protobuf.ByteString
getEmailBytes();