Esta es una referencia de especificación de idioma para la versión 3 del lenguaje del búfer de protocolo (proto3). La sintaxis se especifica mediante el Formulario de Backus-Naur extendido (EBNF):
| alternation () grouping [] option (zero or one time) {} repetition (any number of times)
Para obtener más información sobre el uso de proto3, consulta la guía del lenguaje.
Elementos léxicos
Letras y dígitos
letter = "A" … "Z" | "a" … "z" decimalDigit = "0" … "9" octalDigit = "0" … "7" hexDigit = "0" … "9" | "A" … "F" | "a" … "f"
Identificadores
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
Literales de número entero
intLit = decimalLit | octalLit | hexLit decimalLit = ( "1" … "9" ) { decimalDigit } octalLit = "0" { octalDigit } hexLit = "0" ( "x" | "X" ) hexDigit { hexDigit }
Literales de punto flotante
floatLit = ( decimals "." [ decimals ] [ exponent ] | decimals exponent | "."decimals [ exponent ] ) | "inf" | "nan" decimals = decimalDigit { decimalDigit } exponent = ( "e" | "E" ) [ "+" | "-" ] decimals
Booleano
boolLit = "true" | "false"
Literales de string
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" | '\' | "'" | '"' )
Estado vacío
emptyStatement = ";"
Constante
constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) | strLit | boolLit
Sintaxis
La instrucción de sintaxis se usa para definir la versión de protobuf.
syntax = "syntax" "=" ("'" "proto3" "'" | '"' "proto3" '"') ";"
Ejemplo:
syntax = "proto3";
Declaración de importación
La sentencia import se usa para importar las definiciones de otro .proto.
import = "import" [ "weak" | "public" ] strLit ";"
Ejemplo:
import public "other.proto";
Paquete
El especificador de paquetes se puede usar para evitar conflictos de nombres entre los tipos de mensajes de protocolo.
package = "package" fullIdent ";"
Ejemplo:
package foo.bar;
Opción
Se pueden usar opciones en archivos proto, mensajes, enumeraciones y servicios. Una opción puede ser una opción definida por protobuf o una opción personalizada. Para obtener más información, consulta Opciones en la guía de idiomas.
option = "option" optionName "=" constant ";" optionName = ( ident | "(" fullIdent ")" ) { "." ident }
Ejemplo:
option java_package = "com.example.foo";
Campos
Los campos son los elementos básicos de un mensaje de búfer de protocolo. Los campos pueden ser campos normales, uno de los campos o de mapa. Un campo tiene un tipo y un número de campo.
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | messageType | enumType fieldNumber = intLit;
Campo normal
Cada campo tiene tipo, nombre y número de campo. Puede tener opciones de campo.
field = [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";" fieldOptions = fieldOption { "," fieldOption } fieldOption = optionName "=" constant
Ejemplos:
foo.Bar nested_message = 2; repeated int32 samples = 4 [packed=true];
Campo único y único
Uno de ellos consiste en uno de los campos y un nombre.
oneof = "oneof" oneofName "{" { option | oneofField | emptyStatement } "}" oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
Ejemplo:
oneof foo { string name = 4; SubMessage sub_message = 9; }
Campo de mapa
Un campo de mapa tiene un tipo de clave, un tipo de valor, un nombre y un número de campo. El tipo de clave puede ser cualquier tipo integral o de string.
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]" ] ";" keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"
Ejemplo:
map<string, Project> projects = 3;
Reservado
Las declaraciones reservadas declaran un rango de números de campo o nombres de campo que no se pueden usar en este mensaje.
reserved = "reserved" ( ranges | strFieldNames ) ";" ranges = range { "," range } range = intLit [ "to" ( intLit | "max" ) ] strFieldNames = strFieldName { "," strFieldName } strFieldName = "'" fieldName "'" | '"' fieldName '"'
Ejemplos:
reserved 2, 15, 9 to 11; reserved "foo", "bar";
Definiciones de nivel superior
Definición de enumeración
La definición de enumeración consta de un nombre y un cuerpo de enumeración. El cuerpo de la enumeración puede tener opciones, campos de enumeración y declaraciones reservadas. Las definiciones de enumeración deben comenzar con el valor de enumeración cero.
enum = "enum" enumName enumBody enumBody = "{" { option | enumField | emptyStatement | reserved } "}" enumField = ident "=" [ "-" ] intLit [ "[" enumValueOption { "," enumValueOption } "]" ]";" enumValueOption = optionName "=" constant
Ejemplo:
enum EnumAllowingAlias { option allow_alias = true; EAA_UNSPECIFIED = 0; EAA_STARTED = 1; EAA_RUNNING = 2 [(custom_option) = "hello world"]; }
Definición de mensaje
Un mensaje consta de un nombre y un cuerpo de mensaje. El cuerpo del mensaje puede tener campos, definiciones de enumeraciones anidadas, definiciones de mensajes anidados, opciones, una de ellas, campos de mapas y declaraciones reservadas.
message = "message" messageName messageBody messageBody = "{" { field | enum | message | option | oneof | mapField | reserved | emptyStatement } "}"
Ejemplo:
message Outer { option (my_option).a = true; message Inner { // Level 2 int64 ival = 1; } map<int32, string> my_map = 2; }
Definición del servicio
service = "service" serviceName "{" { option | rpc | emptyStatement } "}" rpc = "rpc" rpcName "(" [ "stream" ] messageType ")" "returns" "(" [ "stream" ] messageType ")" (( "{" {option | emptyStatement } "}" ) | ";")
Ejemplo:
service SearchService { rpc Search (SearchRequest) returns (SearchResponse); }
Archivo proto
proto = syntax { import | package | option | topLevelDef | emptyStatement } topLevelDef = message | enum | service
Un archivo .proto de ejemplo:
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; }