Protocol Buffers Language Specification (Proto3)

Language specification reference for 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.

Lexical Elements

Letters and Digits

letter = "A" ... "Z" | "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 messageType = [ "." ] { ident "." } messageName enumType = [ "." ] { ident "." } enumName 

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.

syntax = "syntax" "=" ("'" "proto3" "'" | '"' "proto3" '"') ";" 

Example:

syntax = "proto3"; 

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 ")" optionNamePart = { ident | "(" ["."] fullIdent ")" } 

Example:

option java_package = "com.example.foo"; 

Fields

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; 

Normal Field

Each field has type, name and field number. It may have field options.

field = [ "repeated" | "optional" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";" fieldOptions = fieldOption { ","  fieldOption } fieldOption = optionName "=" constant 

Examples:

foo.Bar nested_message = 2; repeated int32 samples = 4 [packed=true]; 

Oneof and Oneof Field

A oneof consists of oneof fields and a oneof name.

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.

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

Reserved statements declare a range of field numbers or field names that cannot be used in this message.

reserved = "reserved" ( ranges | strFieldNames ) ";" ranges = range { "," range } range =  intLit [ "to" ( intLit | "max" ) ] 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, 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 | 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; } 

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;   enum E {     foo = 0;   } } 

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 | service 

An example .proto file:

syntax = "proto3"; 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     int64 ival = 1;   }   repeated Inner inner_message = 2;   EnumAllowingAlias enum_field = 3;   map<int32, string> my_map = 4; }