Известные типы Protocol Buffers

Документация API для пакета google.protobuf.

Содержание

Известные типы, оканчивающиеся на "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, которые используют схему http, https или не используют схему, применяются следующие ограничения и интерпретации:

  • Если схема не указана, предполагается https.
  • Последний сегмент пути URL должен представлять полностью квалифицированное имя типа (как в path/google.protobuf.Duration).
  • HTTP GET запрос по URL должен возвращать значение google.protobuf.Type в бинарном формате или вызывать ошибку.
  • Приложениям разрешено кэшировать результаты поиска на основе URL или иметь их предварительно скомпилированными в бинарный файл, чтобы избежать поиска. Поэтому необходимо сохранять бинарную совместимость при изменениях типов. (Используйте версионные имена типов для управления критическими изменениями.)

Схемы, отличные от http, https (или пустой схемы), могут использоваться с семантикой, специфичной для реализации.

value bytes Должен быть допустимым сериализованным данным указанного выше типа.

Api

Api — это легковесный дескриптор для сервиса protobuf.

Имя поля Тип Описание
name string Полностью квалифицированное имя этого api, включая имя пакета, за которым следует простое имя api.
methods Method Методы этого api, в произвольном порядке.
options Option Любые метаданные, прикрепленные к API.
version string

Строка версии для этого api. Если указана, должна иметь вид major-version.minor-version, как в 1.10. Если минорная версия опущена, по умолчанию она равна нулю. Если все поле версии пустое, мажорная версия выводится из имени пакета, как описано ниже. Если поле не пустое, версия в имени пакета будет проверена на соответствие тому, что предоставлено здесь.

Схема версионирования использует семантическое версионирование, где мажорный номер версии указывает на критическое изменение, а минорный — на добавочное, некритическое изменение. Оба номера версий являются сигналами для пользователей о том, чего ожидать от разных версий, и должны быть тщательно выбраны на основе плана продукта.

Мажорная версия также отражается в имени пакета API, которое должно оканчиваться на v<major-version>, как в google.feature.v1. Для мажорных версий 0 и 1 суффикс может быть опущен. Нулевые мажорные версии должны использоваться только для экспериментальных, не-GA API.

source_context SourceContext Исходный контекст для сервиса protobuf, представленного этим сообщением.
mixins Mixin Включенные 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.