This is a language specification reference for version 3 of the Protocol Buffers language (proto3). The syntax is specified using Extended Backus-Naur Form (EBNF):
| alternation
() grouping
[] option (zero or one time)
{} repetition (any number of times)
For more information about using proto3, see the language guide.
letter = "A" … "Z" | "a" … "z"
decimalDigit = "0" … "9"
octalDigit = "0" … "7"
hexDigit = "0" … "9" | "A" … "F" | "a" … "f"
ident = letter { letter | decimalDigit | "_" }
fullIdent = ident { "." ident }
messageName = ident
enumName = ident
fieldName = ident
oneofName = ident
mapName = ident
serviceName = ident
rpcName = ident
messageType = [ "." ] { ident "." } messageName
enumType = [ "." ] { ident "." } enumName
intLit = decimalLit | octalLit | hexLit
decimalLit = ( "1" … "9" ) { decimalDigit }
octalLit = "0" { octalDigit }
hexLit = "0" ( "x" | "X" ) hexDigit { hexDigit }
floatLit = ( decimals "." [ decimals ] [ exponent ] | decimals exponent | "."decimals [ exponent ] ) | "inf" | "nan"
decimals = decimalDigit { decimalDigit }
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals
boolLit = "true" | "false"
strLit = ( "'" { charValue } "'" ) | ( '"' { charValue } '"' )
charValue = hexEscape | octEscape | charEscape | /[^\0\n\\]/
hexEscape = '\' ( "x" | "X" ) hexDigit hexDigit
octEscape = '\' octalDigit octalDigit octalDigit
charEscape = '\' ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | '\' | "'" | '"' )
quote = "'" | '"'
emptyStatement = ";"
constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) | strLit | boolLit
The syntax statement is used to define the protobuf version.
syntax = "syntax" "=" quote "proto3" quote ";"
Example:
syntax = "proto3";
The import statement is used to import another .proto’s definitions.
import = "import" [ "weak" | "public" ] strLit ";"
Example:
import public "other.proto";
The package specifier can be used to prevent name clashes between protocol message types.
package = "package" fullIdent ";"
Example:
package foo.bar;
Options can be used in proto files, messages, enums and services. An option can be a protobuf defined option or a custom option. For more information, see Options in the language guide.
option = "option" optionName "=" constant ";"
optionName = ( ident | "(" fullIdent ")" ) { "." ident }
Example:
option java_package = "com.example.foo";
Fields are the basic elements of a protocol buffer message. Fields can be normal fields, oneof fields, or map fields. A field has a type and field number.
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
| "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
| "bool" | "string" | "bytes" | messageType | enumType
fieldNumber = intLit;
Each field has type, name and field number. It may have field options.
field = [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
fieldOptions = fieldOption { "," fieldOption }
fieldOption = optionName "=" constant
Examples:
foo.bar nested_message = 2;
repeated int32 samples = 4 [packed=true];
A oneof consists of oneof fields and a oneof name.
oneof = "oneof" oneofName "{" { oneofField | emptyStatement } "}"
oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
Example:
oneof foo {
string name = 4;
SubMessage sub_message = 9;
}
A map field has a key type, value type, name, and field number. The key type can be any integral or string type.
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" |
"fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"
Example:
map<string, Project> projects = 3;
Reserved statements declare a range of field numbers or field names that cannot be used in this message.
reserved = "reserved" ( ranges | fieldNames ) ";"
ranges = range { "," range }
range = intLit [ "to" ( intLit | "max" ) ]
fieldNames = fieldName { "," fieldName }
Examples:
reserved 2, 15, 9 to 11;
reserved "foo", "bar";
The enum definition consists of a name and an enum body. The enum body can have options and enum fields. Enum definitions must start with enum value zero.
enum = "enum" enumName enumBody
enumBody = "{" { option | enumField | emptyStatement } "}"
enumField = ident "=" intLit [ "[" enumValueOption { "," enumValueOption } "]" ]";"
enumValueOption = optionName "=" constant
Example:
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}
A message consists of a message name and a message body. The message body can have fields, nested enum definitions, nested message definitions, options, oneofs, map fields, and reserved statements.
message = "message" messageName messageBody
messageBody = "{" { field | enum | message | option | oneof | mapField |
reserved | emptyStatement } "}"
Example:
message Outer {
option (my_option).a = true;
message Inner { // Level 2
int64 ival = 1;
}
map<int32, string> my_map = 2;
}
service = "service" serviceName "{" { option | rpc | emptyStatement } "}"
rpc = "rpc" rpcName "(" [ "stream" ] messageType ")" "returns" "(" [ "stream" ]
messageType ")" (( "{" {option | emptyStatement } "}" ) | ";")
Example:
service SearchService {
rpc Search (SearchRequest) returns (SearchResponse);
}
proto = syntax { import | package | option | topLevelDef | emptyStatement }
topLevelDef = message | enum | service
An example .proto file:
syntax = "proto3";
import public "other.proto";
option java_package = "com.example.foo";
enum EnumAllowingAlias {
option allow_alias = true;
UNKNOWN = 0;
STARTED = 1;
RUNNING = 2 [(custom_option) = "hello world"];
}
message outer {
option (my_option).a = true;
message inner { // Level 2
int64 ival = 1;
}
repeated inner inner_message = 2;
EnumAllowingAlias enum_field =3;
map<int32, string> my_map = 4;
}
(Notice: Origin official document is Here)