Известные типы Protocol Buffers
Документация API для пакета google.protobuf.
Содержание
Any(сообщение)Api(сообщение)BoolValue(сообщение)BytesValue(сообщение)DoubleValue(сообщение)Duration(сообщение)Empty(сообщение)Enum(сообщение)EnumValue(сообщение)Field(сообщение)Field.Cardinality(перечисление)Field.Kind(перечисление)FieldMask(сообщение)FloatValue(сообщение)Int32Value(сообщение)Int64Value(сообщение)ListValue(сообщение)Method(сообщение)Mixin(сообщение)NullValue(перечисление)Option(сообщение)SourceContext(сообщение)StringValue(сообщение)Struct(сообщение)Syntax(перечисление)Timestamp(сообщение)Type(сообщение)UInt32Value(сообщение)UInt64Value(сообщение)Value(сообщение)
Известные типы, оканчивающиеся на "Value", являются сообщениями-обертками для других типов,
такими как BoolValue и EnumValue. Сейчас они устарели. Единственные причины использовать
обертки сегодня:
- Совместимость на уровне передачи данных с сообщениями, которые уже их используют.
- Если нужно поместить скалярное значение в сообщение
Any.
В большинстве случаев есть лучшие варианты:
- Для новых сообщений лучше использовать обычные поля с явным присутствием
(
optionalв proto2/proto3, обычное поле в редакции >= 2023). - Расширения, как правило, являются лучшим вариантом, чем поля
Any.
Any
Any содержит произвольное сериализованное сообщение вместе с URL, который описывает
тип сериализованного сообщения.
JSON
JSON-представление значения Any использует регулярное представление десериализованного,
встроенного сообщения с дополнительным полем @type, которое содержит URL типа. Пример:
package google.profile;
message Person {
string first_name = 1;
string last_name = 2;
}
{
"@type": "type.googleapis.com/google.profile.Person",
"firstName": <string>,
"lastName": <string>
}
Если тип встроенного сообщения является известным и имеет пользовательское JSON-представление,
это представление будет встроено с добавлением поля value, которое содержит
пользовательский JSON в дополнение к полю @type. Пример (для сообщения
google.protobuf.Duration):
{
"@type": "type.googleapis.com/google.protobuf.Duration",
"value": "1.212s"
}
| Имя поля | Тип | Описание |
|---|---|---|
type_url |
string |
URL/имя ресурса, содержимое которого описывает тип сериализованного сообщения. Для URL, которые используют схему
Схемы, отличные от |
value |
bytes |
Должен быть допустимым сериализованным данным указанного выше типа. |
Api
Api — это легковесный дескриптор для сервиса protobuf.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Полностью квалифицированное имя этого api, включая имя пакета, за которым следует простое имя api. |
methods |
Method
|
Методы этого api, в произвольном порядке. |
options |
Option
|
Любые метаданные, прикрепленные к API. |
version |
string |
Строка версии для этого api. Если указана, должна иметь вид
Схема версионирования использует семантическое версионирование, где мажорный номер версии указывает на критическое изменение, а минорный — на добавочное, некритическое изменение. Оба номера версий являются сигналами для пользователей о том, чего ожидать от разных версий, и должны быть тщательно выбраны на основе плана продукта.
Мажорная версия также отражается в имени пакета API,
которое должно оканчиваться на |
source_context |
|
Исходный контекст для сервиса protobuf, представленного этим сообщением. |
mixins |
|
Включенные API. См.
Mixin.
|
syntax |
Syntax
|
Исходный синтаксис сервиса. |
BoolValue
Сообщение-обертка для bool.
JSON-представление для BoolValue — это JSON true и false.
| Имя поля | Тип | Описание |
|---|---|---|
value |
bool |
Логическое значение. |
BytesValue
Сообщение-обертка для bytes.
JSON-представление для BytesValue — это JSON строка.
| Имя поля | Тип | Описание |
|---|---|---|
value |
bytes |
Значение в байтах. |
DoubleValue
Сообщение-обертка для double.
JSON-представление для DoubleValue — это JSON число.
| Имя поля | Тип | Описание |
|---|---|---|
value |
double |
Значение типа double. |
Duration
Duration представляет знаковый, фиксированной длины промежуток времени, представленный как количество секунд и долей секунд с наносекундным разрешением. Он не зависит от любого календаря и понятий, таких как «день» или «месяц». Он связан с Timestamp тем, что разница между двумя значениями Timestamp — это Duration, и его можно добавить или вычесть из Timestamp. Диапазон составляет приблизительно +-10 000 лет.
Пример 1: Вычисление Duration из двух Timestamps в псевдокоде.
Timestamp start = ...;
Timestamp end = ...;
Duration duration = ...;
duration.seconds = end.seconds - start.seconds;
duration.nanos = end.nanos - start.nanos;
if (duration.seconds < 0 && duration.nanos > 0) {
duration.seconds += 1;
duration.nanos -= 1000000000;
} else if (duration.seconds > 0 && duration.nanos < 0) {
duration.seconds -= 1;
duration.nanos += 1000000000;
}
Пример 2: Вычисление Timestamp из Timestamp + Duration в псевдокоде.
Timestamp start = ...;
Duration duration = ...;
Timestamp end = ...;
end.seconds = start.seconds + duration.seconds;
end.nanos = start.nanos + duration.nanos;
if (end.nanos < 0) {
end.seconds -= 1;
end.nanos += 1000000000;
} else if (end.nanos >= 1000000000) {
end.seconds += 1;
end.nanos -= 1000000000;
}
JSON-представление для Duration — это String, который оканчивается на s для
указания секунд и предваряется количеством секунд, с наносекундами,
выраженными как дробные секунды.
| Имя поля | Тип | Описание |
|---|---|---|
seconds |
int64 |
Знаковое количество секунд в промежутке времени. Должно быть от -315 576 000 000 до +315 576 000 000 включительно. |
nanos |
int32 |
Знаковые доли секунды с наносекундным разрешением промежутка времени.
Длительности менее одной секунды представлены с полем seconds, равным 0,
и положительным или отрицательным полем nanos.
Для длительностей в одну секунду или более ненулевое
значение для поля nanos должно иметь тот же знак,
что и поле seconds. Должно быть от -999 999 999 до
+999 999 999 включительно.
|
Empty
Универсальное пустое сообщение, которое можно повторно использовать, чтобы избежать определения дублированных пустых сообщений в ваших API. Типичный пример — использовать его как тип запроса или ответа метода API. Например:
service Foo {
rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
}
JSON-представление для Empty — это пустой JSON объект {}.
Enum
Определение типа перечисления.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Имя типа перечисления. |
enumvalue |
EnumValue
|
Определения значений перечисления. |
options |
Option
|
Опции protobuf. |
source_context |
SourceContext
|
Исходный контекст. |
syntax |
Syntax
|
Исходный синтаксис. |
edition |
string
|
Исходная редакция, если syntax равен SYNTAX_EDITIONS. |
EnumValue
Определение значения перечисления.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Имя значения перечисления. |
number |
int32 |
Числовое значение перечисления. |
options |
Option
|
Опции protobuf. |
Field
Одно поле типа сообщения.
| Имя поля | Тип | Описание |
|---|---|---|
kind |
Kind
|
Тип поля. |
cardinality |
Cardinality
|
Кардинальность поля. |
number |
int32 |
Номер поля. |
name |
string |
Имя поля. |
type_url |
string |
URL типа поля, без схемы, для типов сообщений или перечислений.
Пример:
"type.googleapis.com/google.protobuf.Timestamp".
|
oneof_index |
int32 |
Индекс типа поля в Type.oneofs, для типов сообщений или
перечислений. Первый тип имеет индекс 1; ноль означает, что тип
отсутствует в списке.
|
packed |
bool |
Использовать ли альтернативное упакованное представление при передаче. |
options |
Option
|
Опции protobuf. |
json_name |
string |
JSON-имя поля. |
default_value |
string |
Строковое значение значения по умолчанию этого поля. Только для синтаксиса Proto2. |
Cardinality
Является ли поле опциональным, обязательным или повторяющимся.
| Значение перечисления | Описание |
|---|---|
CARDINALITY_UNKNOWN |
Для полей с неизвестной кардинальностью. |
CARDINALITY_OPTIONAL |
Для опциональных полей. |
CARDINALITY_REQUIRED |
Для обязательных полей. Только для синтаксиса Proto2. |
CARDINALITY_REPEATED |
Для повторяющихся полей. |
Kind
Базовые типы полей.
| Значение перечисления | Описание |
|---|---|
TYPE_UNKNOWN |
Тип поля неизвестен. |
TYPE_DOUBLE |
Тип поля double. |
TYPE_FLOAT |
Тип поля float. |
TYPE_INT64 |
Тип поля int64. |
TYPE_UINT64 |
Тип поля uint64. |
TYPE_INT32 |
Тип поля int32. |
TYPE_FIXED64 |
Тип поля fixed64. |
TYPE_FIXED32 |
Тип поля fixed32. |
TYPE_BOOL |
Тип поля bool. |
TYPE_STRING |
Тип поля string. |
TYPE_GROUP |
Тип поля group. Только для синтаксиса Proto2 и устарел. |
TYPE_MESSAGE |
Тип поля message. |
TYPE_BYTES |
Тип поля bytes. |
TYPE_UINT32 |
Тип поля uint32. |
TYPE_ENUM |
Тип поля enum. |
TYPE_SFIXED32 |
Тип поля sfixed32. |
TYPE_SFIXED64 |
Тип поля sfixed64. |
TYPE_SINT32 |
Тип поля sint32. |
TYPE_SINT64 |
Тип поля sint64. |
FieldMask
FieldMask представляет набор символьных путей к полям, например:
paths: "f.a"
paths: "f.b.d"
Здесь f представляет поле в некотором корневом сообщении, a и b — поля в
сообщении, найденном в f, а d — поле, найденное в сообщении в f.b.
Маски полей используются для указания подмножества полей, которые должны быть возвращены операцией get (проекция), или изменены операцией обновления. Маски полей также имеют пользовательское кодирование JSON (см. ниже).
Маски полей в проекциях
Когда FieldMask указывает проекцию, API отфильтрует ответное
сообщение (или подсообщение), чтобы содержать только те поля, которые указаны в маске. Для
примера, рассмотрим это сообщение ответа «до маскирования»:
f {
a : 22
b {
d : 1
x : 2
}
y : 13
}
z: 8
После применения маски из предыдущего примера ответ API не будет содержать конкретных значений для полей x, y или z (их значение будет установлено в значение по умолчанию и опущено в текстовом выводе proto):
f {
a : 22
b {
d : 1
}
}
Повторяющееся поле не допускается, кроме как на последней позиции маски поля.
Если объект FieldMask отсутствует в операции get, операция применяется
ко всем полям (как если бы была указана FieldMask всех полей).
Обратите внимание, что маска поля не обязательно применяется к ответному сообщению верхнего уровня. В случае операции REST get маска поля применяется непосредственно к ответу, но в случае операции REST list маска вместо этого применяется к каждому отдельному сообщению в возвращаемом списке ресурсов. В случае пользовательского метода REST могут использоваться другие определения. Там, где применяется маска, будет четко задокументировано вместе с ее объявлением в API. В любом случае, влияние на возвращаемый ресурс/ресурсы является обязательным поведением для API.
Маски полей в операциях обновления
Маска поля в операциях обновления указывает, какие поля целевого ресурса будут обновлены. От API требуется изменить только значения полей, указанных в маске, и оставить остальные нетронутыми. Если ресурс передается для описания обновленных значений, API игнорирует значения всех полей, не охваченных маской.
Чтобы сбросить значение поля к значению по умолчанию, поле должно быть в маске и установлено в значение по умолчанию в предоставленном ресурсе. Следовательно, чтобы сбросить все поля ресурса, предоставьте экземпляр по умолчанию ресурса и установите все поля в маске, или не предоставляйте маску, как описано ниже.
Если маска поля отсутствует при обновлении, операция применяется ко всем полям (как если бы была указана маска поля всех полей). Обратите внимание, что в условиях эволюции схемы это может означать, что поля, которые клиент не знает и поэтому не заполнил в запросе, будут сброшены к их значению по умолчанию. Если это нежелательное поведение, конкретный сервис может потребовать от клиента всегда указывать маску поля, выдавая ошибку, если это не так.
Как и в случае с операциями get, расположение ресурса, который описывает обновленные значения в сообщении запроса, зависит от вида операции. В любом случае влияние маски поля должно соблюдаться API.
Соображения для HTTP REST
HTTP-вид операции обновления, которая использует маску поля, должен быть установлен в PATCH вместо PUT для удовлетворения семантики HTTP (PUT должен использоваться только для полных обновлений).
Кодирование JSON масок полей
В JSON маска поля кодируется как одна строка, где пути разделены запятой. Имена полей в каждом пути преобразуются в/из стиля lower-camel.
В качестве примера рассмотрим следующие объявления сообщений:
message Profile {
User user = 1;
Photo photo = 2;
}
message User {
string display_name = 1;
string address = 2;
}
В proto маска поля для Profile может выглядеть так:
mask {
paths: "user.display_name"
paths: "photo"
}
В JSON та же маска представлена ниже:
{
mask: "user.displayName,photo"
}
| Имя поля | Тип | Описание |
|---|---|---|
paths |
string |
Набор путей маски поля. |
FloatValue
Сообщение-обертка для float.
JSON-представление для FloatValue — это JSON число.
| Имя поля | Тип | Описание |
|---|---|---|
value |
float |
Значение типа float. |
Int32Value
Сообщение-обертка для int32.
JSON-представление для Int32Value — это JSON число.
| Имя поля | Тип | Описание |
|---|---|---|
value |
int32 |
Значение типа int32. |
Int64Value
Сообщение-обертка для int64.
JSON-представление для Int64Value — это JSON строка.
| Имя поля | Тип | Описание |
|---|---|---|
value |
int64 |
Значение типа int64. |
ListValue
ListValue — это обертка вокруг повторяющегося поля значений.
JSON-представление для ListValue — это JSON массив.
| Имя поля | Тип | Описание |
|---|---|---|
values |
Value
|
Повторяющееся поле значений динамического типа. |
Method
Method представляет метод api.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Простое имя этого метода. |
request_type_url |
string |
URL типа входного сообщения. |
request_streaming |
bool |
Если true, запрос передается потоком. |
response_type_url |
string |
URL типа выходного сообщения. |
response_streaming |
bool |
Если true, ответ передается потоком. |
options |
Option
|
Любые метаданные, прикрепленные к методу. |
syntax |
Syntax
|
Исходный синтаксис этого метода. |
Mixin
Объявляет API, который должен быть включен в этот API. Включающий API должен переобъявить все методы из включаемого API, но документация и опции наследуются следующим образом:
-
Если после удаления комментариев и пробелов строка документации переобъявленного метода пуста, она будет унаследована от исходного метода.
-
Каждая аннотация, принадлежащая конфигурации сервиса (http, visibility), которая не установлена в переобъявленном методе, будет унаследована.
-
Если аннотация http унаследована, шаблон пути будет изменен следующим образом. Любой префикс версии будет заменен версией включающего API плюс путь
root, если указан.
Пример простого mixin:
package google.acl.v1;
service AccessControl {
// Get the underlying ACL object.
rpc GetAcl(GetAclRequest) returns (Acl) {
option (google.api.http).get = "/v1/{resource=**}:getAcl";
}
}
package google.storage.v2;
service Storage {
// rpc GetAcl(GetAclRequest) returns (Acl);
// Get a data record.
rpc GetData(GetDataRequest) returns (Data) {
option (google.api.http).get = "/v2/{resource=**}";
}
}
Пример конфигурации mixin:
apis:
- name: google.storage.v2.Storage
mixins:
- name: google.acl.v1.AccessControl
Конструкция mixin подразумевает, что все методы в AccessControl также
объявлены с тем же именем и типами запроса/ответа в Storage. Генератор документации
или процессор аннотаций увидит эффективный метод Storage.GetAcl
после наследования документации и аннотаций следующим образом:
service Storage {
// Get the underlying ACL object.
rpc GetAcl(GetAclRequest) returns (Acl) {
option (google.api.http).get = "/v2/{resource=**}:getAcl";
}
...
}
Обратите внимание, как версия в шаблоне пути изменилась с v1 на v2.
Если указано поле root, это должен быть относительный путь,
под которым размещаются унаследованные HTTP-пути. Пример:
apis:
- name: google.storage.v2.Storage
mixins:
- name: google.acl.v1.AccessControl
root: acls
Это подразумевает следующую унаследованную HTTP-аннотацию:
service Storage {
// Get the underlying ACL object.
rpc GetAcl(GetAclRequest) returns (Acl) {
option (google.api.http).get = "/v2/acls/{resource=**}:getAcl";
}
...
}
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Полностью квалифицированное имя API, которое включено. |
root |
string |
Если не пусто, указывает путь, под которым размещаются унаследованные HTTP-пути. |
NullValue
NullValue — это перечисление-одиночка для представления нулевого значения для
объединения типов Value.
JSON-представление для NullValue — это JSON null.
| Значение перечисления | Описание |
|---|---|
NULL_VALUE |
Нулевое значение. |
Option
Опция protobuf, которая может быть прикреплена к сообщению, полю, перечислению и т.д.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Имя опции. Например, "java_package".
|
value |
Any
|
Значение опции. Например,
"com.google.protobuf".
|
SourceContext
SourceContext представляет информацию об источнике элемента protobuf,
например, о файле, в котором он определен.
| Имя поля | Тип | Описание |
|---|---|---|
file_name |
string |
Имя файла .proto с указанием пути, который содержал связанный
элемент protobuf. Например:
"google/protobuf/source.proto".
|
StringValue
Сообщение-обертка для string.
JSON-представление для StringValue — это JSON строка.
| Имя поля | Тип | Описание |
|---|---|---|
value |
string |
Строковое значение. |
Struct
Struct представляет структурированное значение данных, состоящее из полей, которые отображаются в
значения динамического типа. В некоторых языках Struct может поддерживаться
нативным представлением. Например, в скриптовых языках, таких как JS, struct
представлен как объект. Детали этого представления описаны
вместе с поддержкой proto для языка.
JSON-представление для Struct — это JSON объект.
| Имя поля | Тип | Описание |
|---|---|---|
fields |
map<string, Value>
|
Карта значений динамического типа. |
Syntax
Синтаксис, в котором определен элемент protobuf.
| Значение перечисления | Описание |
|---|---|
SYNTAX_PROTO2 |
Синтаксис proto2. |
SYNTAX_PROTO3 |
Синтаксис proto3. |
SYNTAX_EDITIONS |
Синтаксис использует конструкцию edition. |
Timestamp
Timestamp представляет момент времени, не зависящий от любого часового пояса или календаря, представленный как секунды и доли секунд с наносекундным разрешением в UTC эпохи. Он кодируется с использованием Пролептического Григорианского календаря, который расширяет Григорианский календарь назад до первого года. Он кодируется в предположении, что все минуты состоят из 60 секунд, т.е. високосные секунды «размазаны», так что таблица високосных секунд не нужна для интерпретации. Диапазон от 0001-01-01T00:00:00Z до 9999-12-31T23:59:59.999999999Z. Ограничиваясь этим диапазоном, мы гарантируем, что можем конвертировать в строки дат RFC 3339 и обратно. См. https://www.ietf.org/rfc/rfc3339.txt.
Тип Timestamp кодируется как строка в формате RFC 3339:
"{year}-{month}-{day}T{hour}:{min}:{sec}[.{frac_sec}]Z", где {year}
всегда выражается четырьмя цифрами, а {month}, {day}, {hour}, {min},
и {sec} дополняются нулями до двух цифр каждая. Дробные секунды, которые
могут достигать 9 цифр (то есть до разрешения в 1 наносекунду), являются необязательными.
Суффикс "Z" указывает часовой пояс ("UTC"); часовой пояс обязателен.
Сериализатор proto3 JSON должен всегда использовать UTC (как указано "Z") при выводе
типа Timestamp, а парсер proto3 JSON должен быть способен принимать как UTC,
так и другие часовые пояса (как указано смещением).
Пример 1: Вычисление Timestamp из POSIX time().
Timestamp timestamp;
timestamp.set_seconds(time(NULL));
timestamp.set_nanos(0);
Пример 2: Вычисление Timestamp из POSIX gettimeofday().
struct timeval tv;
gettimeofday(&tv, NULL);
Timestamp timestamp;
timestamp.set_seconds(tv.tv_sec);
timestamp.set_nanos(tv.tv_usec * 1000);
Пример 3: Вычисление Timestamp из Win32 GetSystemTimeAsFileTime().
FILETIME ft;
GetSystemTimeAsFileTime(&ft);
UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
// Тик Windows равен 100 наносекундам. Эпоха Windows 1601-01-01T00:00:00Z
// на 11644473600 секунд раньше эпохи Unix 1970-01-01T00:00:00Z.
Timestamp timestamp;
timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
Пример 4: Вычисление Timestamp из Java System.currentTimeMillis().
long millis = System.currentTimeMillis();
Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
.setNanos((int) ((millis % 1000) * 1000000)).build();
Пример 5: Вычисление Timestamp из текущего времени в Python.
now = time.time()
seconds = int(now)
nanos = int((now - seconds) * 10**9)
timestamp = Timestamp(seconds=seconds, nanos=nanos)
| Имя поля | Тип | Описание |
|---|---|---|
seconds |
int64 |
Представляет секунды времени UTC с эпохи Unix 1970-01-01T00:00:00Z. Должно быть от 0001-01-01T00:00:00Z до 9999-12-31T23:59:59Z включительно. |
nanos |
int32 |
Неотрицательные доли секунды с наносекундным разрешением. Отрицательные значения секунд с долями все равно должны иметь неотрицательные значения наносекунд, которые отсчитываются вперед во времени. Должно быть от 0 до 999 999 999 включительно. |
Type
Тип сообщения protobuf.
| Имя поля | Тип | Описание |
|---|---|---|
name |
string |
Полностью квалифицированное имя сообщения. |
fields |
Field
|
Список полей. |
oneofs |
string |
Список типов, появляющихся в определениях oneof в этом
типе.
|
options |
Option
|
Опции protobuf. |
source_context |
SourceContext
|
Исходный контекст. |
syntax |
Syntax
|
Исходный синтаксис. |
UInt32Value
Сообщение-обертка для uint32.
JSON-представление для UInt32Value — это JSON число.
| Имя поля | Тип | Описание |
|---|---|---|
value |
uint32 |
Значение типа uint32. |
UInt64Value
Сообщение-обертка для uint64.
JSON-представление для UInt64Value — это JSON строка.
| Имя поля | Тип | Описание |
|---|---|---|
value |
uint64 |
Значение типа uint64. |
Value
Value представляет значение динамического типа, которое может быть либо null, числом,
строкой, логическим значением, рекурсивным структурным значением или списком значений. Ожидается, что
производитель значения установит один из этих вариантов, отсутствие любого варианта
указывает на ошибку.
JSON-представление для Value — это JSON значение.
| Имя поля | Тип | Описание |
|---|---|---|
| Объединение полей, только одно из следующих: | ||
null_value |
NullValue
|
Представляет нулевое значение. |
number_value |
double |
Представляет значение типа double. Обратите внимание, что попытка сериализовать NaN или Infinity приводит к ошибке. (Мы не можем сериализовать их как строковые значения "NaN" или "Infinity", как мы делаем для обычных полей, потому что они будут анализироваться как string_value, а не number_value). |
string_value |
string |
Представляет строковое значение. |
bool_value |
bool |
Представляет логическое значение. |
struct_value |
Struct
|
Представляет структурированное значение. |
list_value |
ListValue
|
Представляет повторяющийся Value. |