Protocol Buffers Language Specification (Proto2 Syntax)
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 proto2, see the language guide .
Lexical Elements
Letters and Digits
letter = "A" ... "Z" | "a" ... "z"
capitalLetter = "A" ... "Z"
decimalDigit = "0" ... "9"
octalDigit = "0" ... "7"
hexDigit = "0" ... "9" | "A" ... "F" | "a" ... "f"
Identifiers
ident
=
letter
{
letter
|
decimalDigit
|
"_"
}
fullIdent
=
ident
{
"."
ident
}
messageName
=
ident
enumName
=
ident
fieldName
=
ident
oneofName
=
ident
mapName
=
ident
serviceName
=
ident
rpcName
=
ident
streamName
=
ident
messageType
=
[
"."
]
{
ident
"."
}
messageName
enumType
=
[
"."
]
{
ident
"."
}
enumName
groupName
=
capitalLetter
{
letter
|
decimalDigit
|
"_"
}
Integer Literals
intLit = decimalLit | octalLit | hexLit
decimalLit = [-] ( "1" ... "9" ) { decimalDigit }
octalLit = [-] "0" { octalDigit }
hexLit = [-] "0" ( "x" | "X" ) hexDigit { hexDigit }
Floating-point Literals
floatLit = [-] ( decimals "." [ decimals ] [ exponent ] | decimals exponent | "."decimals [ exponent ] ) | "inf" | "nan"
decimals = [-] decimalDigit { decimalDigit }
exponent = ( "e" | "E" ) [ "+" | "-" ] decimals
Boolean
boolLit = "true" | "false"
String Literals
strLit = strLitSingle { strLitSingle }
strLitSingle = ( "'" { charValue } "'" ) | ( '"' { charValue } '"' )
charValue = hexEscape | octEscape | charEscape | unicodeEscape | unicodeLongEscape | /[^\0\n\\]/
hexEscape = '\' ( "x" | "X" ) hexDigit [ hexDigit ]
octEscape = '\' octalDigit [ octalDigit [ octalDigit ] ]
charEscape = '\' ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | '\' | "'" | '"' )
unicodeEscape = '\' "u" hexDigit hexDigit hexDigit hexDigit
unicodeLongEscape = '\' "U" ( "000" hexDigit hexDigit hexDigit hexDigit hexDigit |
"0010" hexDigit hexDigit hexDigit hexDigit
EmptyStatement
emptyStatement = ";"
Constant
constant
=
fullIdent
|
(
[
"-"
|
"+"
]
intLit
)
|
(
[
"-"
|
"+"
]
floatLit
)
|
strLit
|
boolLit
|
MessageValue
MessageValue
is defined in the Text Format Language Specification
.
Syntax
The syntax statement is used to define the protobuf version. If syntax
is
omitted, the protocol compiler will use proto2
. For the sake of clarity, it’s
recommended to always explicitly include a syntax
statement in your .proto
files.
syntax = "syntax" "=" ("'" "proto2" "'" | '"' "proto2" '"') ";"
Import Statement
The import statement is used to import another .proto’s definitions.
import = "import" [ "weak" | "public" ] strLit ";"
Example:
import
public
"other.proto"
;
Package
The package specifier can be used to prevent name clashes between protocol message types.
package
=
"package"
fullIdent
";"
Example:
package
foo
.
bar
;
Option
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
|
bracedFullIdent
)
{
"."
(
ident
|
bracedFullIdent
)
}
bracedFullIdent
=
"("
[
"."
]
fullIdent
")"
For examples:
option
java_package
=
"com.example.foo"
;
Fields
Fields are the basic elements of a protocol buffer message. Fields can be normal
fields, group fields, oneof fields, or map fields. A field has a type, name, and
field number. In proto2, fields also have a label ( required
, optional
, or repeated
).
label
=
"required"
|
"optional"
|
"repeated"
type
=
"double"
|
"float"
|
"int32"
|
"int64"
|
"uint32"
|
"uint64"
|
"sint32"
|
"sint64"
|
"fixed32"
|
"fixed64"
|
"sfixed32"
|
"sfixed64"
|
"bool"
|
"string"
|
"bytes"
|
messageType
|
enumType
fieldNumber
=
intLit
;
Normal field
Each field has a type, name and field number. It may have field options. Note that labels are optional only for oneof fields.
field
=
[
label
]
type
fieldName
"="
fieldNumber
[
"["
fieldOptions
"]"
]
";"
fieldOptions
=
fieldOption
{
","
fieldOption
}
fieldOption
=
optionName
"="
constant
Examples:
optional
foo.bar
nested_message
=
2
;
repeated
int32
samples
=
4
[
packed
=
true
];
Group field
Note that this feature is deprecated and should not be used when creating new message types. Use nested message types instead.
Groups are one way to nest information in message definitions. The group name must begin with capital letter.
group = label "group" groupName "=" fieldNumber messageBody
Example:
repeated
group
Result
=
1
{
required
string
url
=
1
;
optional
string
title
=
2
;
repeated
string
snippets
=
3
;
}
Oneof and oneof field
A oneof consists of oneof fields and a oneof name. Oneof fields do not have labels.
oneof = "oneof" oneofName "{" { option | oneofField } "}"
oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
Example:
oneof
foo
{
string
name
=
4
;
SubMessage
sub_message
=
9
;
}
Map field
A map field has a key type, value type, name, and field number. The key type can be any integral or string type. Note, the key type may not be an enum.
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
;
Extensions and Reserved
Extensions and reserved are message elements that declare a range of field numbers or field names.
Extensions
Extensions declare that a range of field numbers in a message are available for third-party extensions. Other people can declare new fields for your message type with those numeric tags in their own .proto files without having to edit the original file.
extensions = "extensions" ranges ";"
ranges = range { "," range }
range = intLit [ "to" ( intLit | "max" ) ]
Examples:
extensions
100
to
199
;
extensions
4
,
20
to
max
;
For more on this topic, see Extension Declarations .
Reserved
Reserved declares a range of field numbers or field names in a message that can not be used.
reserved = "reserved" ( ranges | strFieldNames ) ";"
strFieldNames = strFieldName { "," strFieldName }
strFieldName = "'" fieldName "'" | '"' fieldName '"'
Examples:
reserved
2
,
15
,
9
to
11
;
reserved
"foo"
,
"bar"
;
Top Level definitions
Enum definition
The enum definition consists of a name and an enum body. The enum body can have options, enum fields, and reserved statements.
enum
=
"enum"
enumName
enumBody
enumBody
=
"{"
{
option
|
enumField
|
emptyStatement
|
reserved
}
"}"
enumField
=
ident
"="
[
"-"
]
intLit
[
"["
enumValueOption
{
","
enumValueOption
}
"]"
]
";"
enumValueOption
=
optionName
"="
constant
Example:
enum
EnumAllowingAlias
{
option
allow_alias
=
true
;
EAA_UNSPECIFIED
=
0
;
EAA_STARTED
=
1
;
EAA_RUNNING
=
2
[(
custom_option
)
=
"hello world"
];
}
Message definition
A message consists of a message name and a message body. The message body can have fields, nested enum definitions, nested message definitions, extend statements, extensions, groups, options, oneofs, map fields, and reserved statements. A message cannot contain two fields with the same name in the same message schema.
message
=
"message"
messageName
messageBody
messageBody
=
"{"
{
field
|
enum
|
message
|
extend
|
extensions
|
group
|
option
|
oneof
|
mapField
|
reserved
|
emptyStatement
}
"}"
Example:
message
Outer
{
option
(
my_option
)
.
a
=
true
;
message
Inner
{
// Level 2
required
int64
ival
=
1
;
}
map
<
int32
,
string
>
my_map
=
2
;
extensions
20
to
30
;
}
None of the entities declared inside a message may have conflicting names. All of the following are prohibited:
message
MyMessage
{
optional
string
foo
=
1
;
message
foo
{}
}
message
MyMessage
{
optional
string
foo
=
1
;
oneof
foo
{
string
bar
=
2
;
}
}
message
MyMessage
{
optional
string
foo
=
1
;
extend
Extendable
{
optional
string
foo
=
2
;
}
}
message
MyMessage
{
optional
string
foo
=
1
;
enum
E
{
foo
=
0
;
}
}
Extend
If a message in the same or imported .proto file has reserved a range for extensions, the message can be extended.
extend = "extend" messageType "{" {field | group} "}"
Example:
extend
Foo
{
optional
int32
bar
=
126
;
}
Service definition
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 file
proto
=
[
syntax
]
{
import
|
package
|
option
|
topLevelDef
|
emptyStatement
}
topLevelDef
=
message
|
enum
|
extend
|
service
An example .proto
file:
syntax
=
"proto2"
;
import
public
"other.proto"
;
option
java_package
=
"com.example.foo"
;
enum
EnumAllowingAlias
{
option
allow_alias
=
true
;
EAA_UNSPECIFIED
=
0
;
EAA_STARTED
=
1
;
EAA_RUNNING
=
1
;
EAA_FINISHED
=
2
[(
custom_option
)
=
"hello world"
];
}
message
Outer
{
option
(
my_option
)
.
a
=
true
;
message
Inner
{
// Level 2
required
int64
ival
=
1
;
}
repeated
Inner
inner_message
=
2
;
optional
EnumAllowingAlias
enum_field
=
3
;
map
<
int32
,
string
>
my_map
=
4
;
extensions
20
to
30
;
}
message
Foo
{
optional
group
GroupMessage
=
1
{
optional
bool
a
=
1
;
}
}