Protocol Buffers Version 2 Language Specification

Protocol Buffers 語言版本 2 (proto2) 的語言規範參考。

語法使用 擴展巴科斯-諾爾範式 (EBNF) 指定

|   alternation
()  grouping
[]  option (zero or one time)
{}  repetition (any number of times)

有關使用 proto2 的更多資訊,請參閱語言指南

詞法元素

字母和數字

letter = "A" ... "Z" | "a" ... "z"
capitalLetter =  "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
streamName = ident
messageType = [ "." ] { ident "." } messageName
enumType = [ "." ] { ident "." } enumName
groupName = capitalLetter { letter | decimalDigit | "_" }

整數文字

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 = 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 = ";"

常數

constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) |
                strLit | boolLit | MessageValue

MessageValue文字格式語言規範中定義。

語法

syntax 語句用於定義 protobuf 版本。

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

匯入語句

import 語句用於匯入另一個 .proto 的定義。

import = "import" [ "weak" | "public" ] strLit ";"

範例

import public "other.proto";

套件

套件指定詞可用於防止協定訊息類型之間的名稱衝突。

package = "package" fullIdent ";"

範例

package foo.bar;

選項

選項可用於 proto 檔案、訊息、列舉和服務。選項可以是 protobuf 定義的選項或自訂選項。如需更多資訊,請參閱語言指南中的選項

option = "option" optionName  "=" constant ";"
optionName = ( ident | bracedFullIdent ) { "." ( ident | bracedFullIdent ) }
bracedFullIdent = "(" ["."] fullIdent ")"

範例

option java_package = "com.example.foo";

欄位

欄位是協定緩衝區訊息的基本元素。欄位可以是普通欄位、群組欄位、oneof 欄位或 map 欄位。欄位具有標籤、類型和欄位編號。

label = "required" | "optional" | "repeated"
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
      | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
      | "bool" | "string" | "bytes" | messageType | enumType
fieldNumber = intLit;

一般欄位

每個欄位都有標籤、類型、名稱和欄位編號。它可能具有欄位選項。

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

範例

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

群組欄位

請注意,此功能已棄用,建立新的訊息類型時不應使用 – 請改用巢狀訊息類型。

群組是在訊息定義中巢狀資訊的一種方式。群組名稱必須以大寫字母開頭。

group = label "group" groupName "=" fieldNumber messageBody

範例

repeated group Result = 1 {
    required string url = 1;
    optional string title = 2;
    repeated string snippets = 3;
}

Oneof 和 oneof 欄位

oneof 由 oneof 欄位和 oneof 名稱組成。Oneof 欄位沒有標籤。

oneof = "oneof" oneofName "{" { option | oneofField } "}"
oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"

範例

oneof foo {
    string name = 4;
    SubMessage sub_message = 9;
}

Map 欄位

map 欄位具有鍵類型、值類型、名稱和欄位編號。鍵類型可以是任何整數或字串類型。請注意,鍵類型不能是列舉。

mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" |
          "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"

範例

map<string, Project> projects = 3;

擴充功能和保留

擴充功能和保留是宣告欄位編號或欄位名稱範圍的訊息元素。

擴充功能

擴充功能宣告訊息中欄位編號範圍可用於第三方擴充功能。其他人可以使用這些數字標籤在他們自己的 .proto 檔案中為您的訊息類型宣告新欄位,而無需編輯原始檔案。

extensions = "extensions" ranges ";"
ranges = range { "," range }
range =  intLit [ "to" ( intLit | "max" ) ]

範例

extensions 100 to 199;
extensions 4, 20 to max;

有關此主題的更多資訊,請參閱擴充功能宣告

保留

Reserved 宣告訊息中不能使用的欄位編號或欄位名稱範圍。

reserved = "reserved" ( ranges | strFieldNames ) ";"
strFieldNames = strFieldName { "," strFieldName }
strFieldName = "'" fieldName "'" | '"' fieldName '"'

範例

reserved 2, 15, 9 to 11;
reserved "foo", "bar";

頂層定義

列舉定義

列舉定義由名稱和列舉主體組成。列舉主體可以具有選項、列舉欄位和 reserved 語句。

enum = "enum" enumName enumBody
enumBody = "{" { option | enumField | emptyStatement | reserved } "}"
enumField = ident "=" [ "-" ] intLit [ "[" enumValueOption { ","  enumValueOption } "]" ]";"
enumValueOption = optionName "=" constant

範例

enum EnumAllowingAlias {
  option allow_alias = true;
  EAA_UNSPECIFIED = 0;
  EAA_STARTED = 1;
  EAA_RUNNING = 2 [(custom_option) = "hello world"];
}

訊息定義

訊息由訊息名稱和訊息主體組成。訊息主體可以具有欄位、巢狀列舉定義、巢狀訊息定義、extend 語句、擴充功能、群組、選項、oneof、map 欄位和 reserved 語句。訊息在同一個訊息結構描述中不能包含兩個名稱相同的欄位。

message = "message" messageName messageBody
messageBody = "{" { field | enum | message | extend | extensions | group |
option | oneof | mapField | reserved | emptyStatement } "}"

範例

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;
}

訊息內宣告的實體都不能有衝突的名稱。以下所有情況均被禁止

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

如果相同或匯入的 .proto 檔案中的訊息已為擴充功能保留範圍,則可以擴充該訊息。

extend = "extend" messageType "{" {field | group} "}"

範例

extend Foo {
  optional int32 bar = 126;
}

服務定義

service = "service" serviceName "{" { option | rpc | emptyStatement } "}"
rpc = "rpc" rpcName "(" [ "stream" ] messageType ")" "returns" "(" [ "stream" ]
messageType ")" (( "{" { option | emptyStatement } "}" ) | ";" )

範例

service SearchService {
  rpc Search (SearchRequest) returns (SearchResponse);
}

Proto 檔案

proto = [syntax] { import | package | option | topLevelDef | emptyStatement }
topLevelDef = message | enum | extend | service

範例 .proto 檔案

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;
  }
}