Настройки функций для редакций

Функции редакций Protobuf и как они влияют на поведение protobuf.

В этой теме представлен обзор функций, включенных в выпущенные версии редакций. Функции последующих редакций будут добавлены в эту тему. Мы анонсируем новые редакции в разделе Новости.

Прежде чем настраивать параметры функций в вашем новом содержимом определения схемы, убедитесь, что вы понимаете, зачем вы их используете. Избегайте карго-культа (cargo-culting) с функциями.

Prototiller

Prototiller — это инструмент командной строки, который обновляет файлы конфигурации схемы proto между версиями синтаксиса и редакциями. Он еще не выпущен, но на него ссылаются throughout этой теме.

Функции

В следующих разделах приведены все поведения, которые можно настроить с помощью функций в редакциях. Сохранение поведения Proto2 или Proto3 показывает, как переопределить поведения по умолчанию, чтобы ваши файлы определений proto вели себя как файлы proto2 или proto3. Для получения дополнительной информации о том, как редакции и функции вместе работают для установки поведения, см. Обзор редакций Protobuf.

Настройки функций применяются на разных уровнях:

На уровне файла: Эти настройки применяются ко всем элементам (сообщениям, полям, перечислениям и т.д.), которые не имеют переопределяющей настройки.

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

Вложенные: Oneof, сообщения и перечисления могут переопределять настройки из сообщения, в которое они вложены.

Самый низкий уровень: Поля, расширения, значения перечислений, диапазоны расширений и методы — это самый низкий уровень, на котором вы можете переопределять настройки.

Каждый из следующих разделов содержит комментарий, в котором указано, к какой области видимости функция может быть применена. Следующий пример показывает mock-функцию, примененную к каждой области видимости:

edition = "2024";

// Определение на уровне файла
option features.bar = BAZ;

enum Foo {
  // Определение на уровне перечисления (не вложенная область)
  option features.bar = QUX;

  A = 1;
  B = 2;
}

message Corge {
  // Определение на уровне сообщения (не вложенная область)
  option features.bar = QUUX;

  message Garply {
    // Определение на уровне сообщения (вложенная область)
    option features.bar = WALDO;
    string id = 1;
  }

  // Определение на уровне поля (самый низкий уровень)
  Foo A = 1 [features.bar = GRAULT];
}

В этом примере настройка "GRAULT" в определении функции на самом низком уровне переопределяет настройку "QUUX" в не вложенной области. И внутри сообщения Garply "WALDO" переопределяет "QUUX".

features.default_symbol_visibility

Эта функция позволяет устанавливать видимость по умолчанию для сообщений и перечислений, делая их доступными или недоступными при импорте другими protobuf. Использование этой функции уменьшит количество мертвых символов, чтобы создавать меньшие бинарные файлы.

В дополнение к установке значений по умолчанию для всего файла, вы можете использовать ключевые слова local и export для установки поведения для каждого поля. Подробнее об этом читайте в разделе Ключевые слова export / local.

Доступные значения:

  • EXPORT_ALL: Это значение по умолчанию до Редакции 2024. Все сообщения и перечисления экспортируются по умолчанию.
  • EXPORT_TOP_LEVEL: Все символы верхнего уровня по умолчанию экспортируются; вложенные по умолчанию являются локальными.
  • LOCAL_ALL: Все символы по умолчанию являются локальными.
  • STRICT: Все символы локальны по умолчанию. Вложенные типы не могут быть экспортированы, за исключением особого случая для message { enum {} reserved 0 to max; }. Это станет значением по умолчанию в будущей редакции.

Применимо к следующей области видимости: Enum, Message

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024EXPORT_TOP_LEVEL
2023EXPORT_ALL
proto3EXPORT_ALL
proto2EXPORT_ALL

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример показывает, как вы можете применить функцию к элементам в ваших файлах определений схемы proto:

// foo.proto
edition = "2024";

// Видимость символов по умолчанию EXPORT_TOP_LEVEL. Установка
// default_symbol_visibility переопределяет эти значения по умолчанию
option features.default_symbol_visibility = LOCAL_ALL;

// Символы верхнего уровня экспортируются по умолчанию в Редакции 2024; применение ключевого слова local
// переопределяет это
export message LocalMessage {
  int32 baz = 1;
  // Вложенные символы являются локальными по умолчанию в Редакции 2024; применение ключевого слова export
  // переопределяет это
  enum ExportedNestedEnum {
    UNKNOWN_EXPORTED_NESTED_ENUM_VALUE = 0;
  }
}

// bar.proto
edition = "2024";

import "foo.proto";

message ImportedMessage {
  // Следующее допустимо, потому что импортированное сообщение явно переопределяет
  // настройку видимости в foo.proto
  LocalMessage bar = 1;

  // Следующее недопустимо, потому что default_symbol_visibility установлен в
  // `LOCAL_ALL`
  // LocalMessage.ExportedNestedEnum qux = 2;
}

features.enforce_naming_style

Введена в Редакции 2024, эта функция включает строгое соблюдение стиля именования, как определено в руководстве по стилю, чтобы гарантировать возможность кругового обмена (round-trippable) protobuf по умолчанию, с возможностью отказаться от этого с помощью значения функции.

Доступные значения:

  • STYLE2024: Обеспечивает строгое соблюдение руководства по стилю для именования.
  • STYLE_LEGACY: Применяет уровень соблюдения руководства по стилю, действовавший до Редакции 2024.

Применимо к следующей области видимости: File

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024STYLE2024
2023STYLE_LEGACY
proto3STYLE_LEGACY
proto2STYLE_LEGACY

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл Редакции 2023:

Редакция 2023 по умолчанию использует STYLE_LEGACY, поэтому некорректное имя поля допустимо:

edition = "2023";

message Foo {
  // Некорректное имя поля не является проблемой
  int64 bar_1 = 1;
}

Редакция 2024 по умолчанию использует STYLE2024, поэтому требуется переопределение, чтобы сохранить некорректное имя поля:

edition = "2024";

// Чтобы сохранить некорректное имя поля, переопределите настройку STYLE2024
option features.enforce_naming_style = STYLE_LEGACY;

message Foo {
  int64 bar_1 = 1;
}

features.enum_type

Эта функция устанавливает поведение для обработки значений перечислений, которые не содержатся в определенном наборе. См. Поведение перечислений для получения дополнительной информации об открытых и закрытых перечислениях.

Эта функция не влияет на файлы proto3, поэтому в этом разделе нет примеров "до" и "после" для файла proto3.

Доступные значения:

  • CLOSED: Закрытые перечисления сохраняют значения перечислений, находящиеся вне диапазона, в наборе неизвестных полей.
  • OPEN: Открытые перечисления разбирают значения вне диапазона непосредственно в их поля.

Применимо к следующим областям видимости: File, Enum

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024OPEN
2023OPEN
proto3OPEN
proto2CLOSED

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

enum Foo {
  A = 2;
  B = 4;
  C = 6;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

enum Foo {
  // Установка функции enum_type переопределяет перечисление OPEN по умолчанию
  option features.enum_type = CLOSED;
  A = 2;
  B = 4;
  C = 6;
}

features.field_presence

Эта функция устанавливает поведение для отслеживания присутствия поля, то есть концепции имеет ли поле protobuf значение.

Доступные значения:

  • LEGACY_REQUIRED: Поле является обязательным для разбора и сериализации. Любое явно установленное значение сериализуется в бинарный формат (даже если оно совпадает со значением по умолчанию).
  • EXPLICIT: Поле имеет явное отслеживание присутствия. Любое явно установленное значение сериализуется в бинарный формат (даже если оно совпадает со значением по умолчанию). Для сингулярных примитивных полей генерируются функции has_* для полей, установленных в EXPLICIT.
  • IMPLICIT: Поле не имеет отслеживания присутствия. Значение по умолчанию не сериализуется в бинарный формат (даже если оно явно установлено). Функции has_* не генерируются для полей, установленных в IMPLICIT.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024EXPLICIT
2023EXPLICIT
proto3IMPLICIT*
proto2EXPLICIT

* proto3 использует IMPLICIT, если только у поля нет метки optional, в этом случае оно ведет себя как EXPLICIT. См. Присутствие в API Proto3 для получения дополнительной информации.

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message Foo {
  required int32 x = 1;
  optional int32 y = 2;
  repeated int32 z = 3;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

message Foo {
  // Установка функции field_presence сохраняет поведение required из proto2
  int32 x = 1 [features.field_presence = LEGACY_REQUIRED];
  int32 y = 2;
  repeated int32 z = 3;
}

Следующий пример показывает файл proto3:

syntax = "proto3";

message Bar {
  int32 x = 1;
  optional int32 y = 2;
  repeated int32 z = 3;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";
// Установка функции field_presence на уровне файла соответствует неявному значению по умолчанию proto3
option features.field_presence = IMPLICIT;

message Bar {
  int32 x = 1;
  // Установка field_presence здесь сохраняет явное состояние, которое поле proto3
  // имеет из-за синтаксиса optional
  int32 y = 2 [features.field_presence = EXPLICIT];
  repeated int32 z = 3;
}

Обратите внимание, что метки required и optional больше не существуют в Редакциях, так как соответствующее поведение устанавливается явно с помощью функции field_presence.

features.json_format

Эта функция устанавливает поведение для разбора и сериализации JSON.

Эта функция не влияет на файлы proto3, поэтому в этом разделе нет примеров "до" и "после" для файла proto3. Поведение редакций соответствует поведению в proto3.

Доступные значения:

  • ALLOW: Среда выполнения должна разрешать разбор и сериализацию JSON. Проверки применяются на уровне proto, чтобы убедиться, что существует четко определенное отображение в JSON.
  • LEGACY_BEST_EFFORT: Среда выполнения делает все возможное для разбора и сериализации JSON. Разрешены определенные protobuf, которые могут привести к неопределенному поведению во время выполнения (например, отображения многие:1 или 1:многие).

Применимо к следующим областям видимости: File, Message, Enum

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024ALLOW
2023ALLOW
proto3ALLOW
proto2LEGACY_BEST_EFFORT

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message Foo {
  // Только предупреждение
  string bar = 1;
  string bar_ = 2;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";
option features.json_format = LEGACY_BEST_EFFORT;

message Foo {
  string bar = 1;
  string bar_ = 2;
}

features.message_encoding

Эта функция устанавливает поведение для кодирования полей при сериализации.

Эта функция не влияет на файлы proto3, поэтому в этом разделе нет примеров "до" и "после" для файла proto3.

В зависимости от языка, поля, которые являются "group-подобными", могут иметь неожиданное использование заглавных букв в сгенерированном коде и в текстовом формате, чтобы обеспечить обратную совместимость с proto2. Поля сообщений являются "group-подобными", если выполняются все следующие условия:

  • Указано кодирование сообщения DELIMITED
  • Тип сообщения определен в той же области видимости, что и поле
  • Имя поля точно соответствует имени типа в нижнем регистре

Доступные значения:

  • LENGTH_PREFIXED: Поля кодируются с использованием типа бинарного формата LEN, описанного в Структура сообщения.
  • DELIMITED: Поля типа message кодируются как groups.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024LENGTH_PREFIXED
2023LENGTH_PREFIXED
proto3LENGTH_PREFIXED
proto2LENGTH_PREFIXED

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message Foo {
  group Bar = 1 {
    optional int32 x = 1;
    repeated int32 y = 2;
  }
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

message Foo {
  message Bar {
    int32 x = 1;
    repeated int32 y = 2;
  }
  Bar bar = 1 [features.message_encoding = DELIMITED];
}

features.repeated_field_encoding

Эта функция — это то, во что была мигрирована опция packed для repeated полей в proto2/proto3 в Редакциях.

Доступные значения:

  • PACKED: Repeated поля примитивного типа кодируются как одна запись LEN, которая содержит каждый элемент, объединенный вместе.
  • EXPANDED: Repeated поля кодируются с номером поля для каждого значения.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024PACKED
2023PACKED
proto3PACKED
proto2EXPANDED

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message Foo {
  repeated int32 bar = 6 [packed=true];
  repeated int32 baz = 7;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";
option features.repeated_field_encoding = EXPANDED;

message Foo {
  repeated int32 bar = 6 [features.repeated_field_encoding=PACKED];
  repeated int32 baz = 7;
}

Следующий пример показывает файл proto3:

syntax = "proto3";

message Foo {
  repeated int32 bar = 6;
  repeated int32 baz = 7 [packed=false];
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

message Foo {
  repeated int32 bar = 6;
  repeated int32 baz = 7 [features.repeated_field_encoding=EXPANDED];
}

features.utf8_validation

Эта функция устанавливает, как проверяются строки. Она применяется ко всем языкам, кроме тех, для которых есть специфичная для языка функция utf8_validation, которая переопределяет ее. См. features.(pb.java).utf8_validation для специфичной для Java функции.

Эта функция не влияет на файлы proto3, поэтому в этом разделе нет примеров "до" и "после" для файла proto3.

Доступные значения:

  • VERIFY: Среда выполнения должна проверять UTF-8. Это поведение по умолчанию для proto3.
  • NONE: Поле ведет себя как непроверенное поле bytes в бинарном формате. Парсеры могут обрабатывать этот тип поля непредсказуемым образом, например, заменяя недопустимые символы. Это поведение по умолчанию для proto2.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024VERIFY
2023VERIFY
proto3VERIFY
proto2NONE

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message MyMessage {
  string foo = 1;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

message MyMessage {
  string foo = 1 [features.utf8_validation = NONE];
}

Специфичные для языка функции

Некоторые функции применяются к определенным языкам и не применяются к тем же protobuf на других языках. Использование этих функций требует от вас импорта соответствующего файла *_features.proto из среды выполнения языка. Примеры в следующих разделах показывают эти импорты.

features.(pb.go).api_level

Языки: Go

Функция api_level позволяет выбрать, для какой версии API плагин Go protobuf должен генерировать код. Opaque API — это последняя версия реализации Protocol Buffers для языка программирования Go. Предыдущая версия теперь называется Open Struct API. См. Go Protobuf: выпуск Opaque API (блог пост) для введения.

Доступные значения:

  • API_OPEN: Open Struct API генерирует типы структур, которые открыты для прямого доступа.
  • API_HYBRID: Hybrid — это шаг между Open и Opaque: Hybrid API также включает методы доступа (так что вы можете обновить свой код), но все еще экспортирует поля структуры как раньше. Нет разницы в производительности; этот уровень API только помогает с миграцией.
  • API_OPAQUE: С Opaque API поля структуры скрыты и больше не могут быть доступны напрямую. Вместо этого новые методы доступа позволяют получать, устанавливать или очищать поле.

Применимо к следующим областям видимости: Message, File

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2023API_OPEN
2024API_OPAQUE

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Вы можете установить функцию api_level, начиная с редакции 2023:

edition = "2023";

import "google/protobuf/go_features.proto";

// Удалите эту строку после миграции кода на Opaque API.
option features.(pb.go).api_level = API_HYBRID;

См. также: Opaque API: Миграция

features.(pb.cpp).enum_name_uses_string_view

Языки: C++

До Редакции 2024 все сгенерированные типы перечислений предоставляли следующую функцию для получения метки из значения перечисления, что создавало некоторые накладные расходы на создание экземпляров std::string во время выполнения:

const std::string& Foo_Name(int);

Значение функции по умолчанию в Редакции 2024 изменяет эту сигнатуру на возврат absl::string_view, чтобы позволить лучшее разделение хранилища и потенциальную экономию памяти/ЦП. Если вы еще не готовы к миграции, вы можете переопределить это, чтобы вернуть предыдущее поведение. См. Тип возвращаемого значения string_view в руководстве по миграции для получения дополнительной информации по этой теме.

Доступные значения:

  • true: Перечисление использует string_view для своих значений.
  • false: Перечисление использует std::string для своих значений.

Применимо к следующим областям видимости: Enum, File

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024true
2023false
proto3false
proto2false

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

features.(pb.java).large_enum

Языки: Java

Эта специфичная для языка функция позволяет использовать новую функциональность, которая обрабатывает большие перечисления в Java, не вызывая ошибок компилятора. Обратите внимание, что эта функция воспроизводит поведение, подобное перечислению, но имеет некоторые заметные различия. Например, операторы switch не поддерживаются.

Доступные значения:

  • true: Java перечисления будут использовать новую функциональность.
  • false: Java перечисления будут продолжать использовать Java перечисления.

Применимо к следующим областям видимости: Enum

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024false
2023false
proto3false
proto2false

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

features.(pb.cpp/pb.java).legacy_closed_enum

Языки: C++, Java

Эта функция определяет, должно ли поле с открытым типом перечисления вести себя так, как если бы оно было закрытым перечислением. Это позволяет редакциям воспроизводить несоответствующее поведение в Java и C++ из proto2 и proto3.

Эта функция не влияет на файлы proto3, и поэтому в этом разделе нет примеров "до" и "после" для файла proto3.

Доступные значения:

  • true: Рассматривает перечисление как закрытое независимо от enum_type.
  • false: Уважает то, что установлено в enum_type.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024false
2023false
proto3false
proto2true

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

import "myproject/proto3file.proto";

message Msg {
  myproject.proto3file.Proto3Enum name = 1;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

import "myproject/proto3file.proto";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

message Msg {
  myproject.proto3file.Proto3Enum name = 1 [
    features.(pb.cpp).legacy_closed_enum = true,
    features.(pb.java).legacy_closed_enum = true
  ];
}

features.(pb.java).nest_in_file_class

Языки: Java

Эта функция управляет тем, будет ли генератор Java вкладывать сгенерированный класс в класс сгенерированного файла Java. Установка этой опции в NO эквивалентна установке java_multiple_files = true в proto2/proto3/редакции 2023.

Имя внешнего класса по умолчанию также обновлено, чтобы всегда быть именем файла .proto в верблюжьем регистре с суффиксом Proto по умолчанию (например, foo/bar_baz.proto становится BarBazProto). Вы все еще можете переопределить это, используя опцию файла java_outer_classname и заменить значение по умолчанию до Редакции 2024, которое было BarBaz или BarBazOuterClass в зависимости от наличия конфликтов.

Доступные значения:

  • NO: Не вкладывать сгенерированный класс в класс файла.
  • YES: Вкладывать сгенерированный класс в класс файла.
  • Legacy: Внутреннее значение, используемое когда установлена опция java_multiple_files.

Применимо к следующим областям видимости: Message, Enum, Service

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024NO
2023LEGACY
proto3LEGACY
proto2LEGACY

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

features.(pb.cpp).string_type

Языки: C++

Эта функция определяет, как сгенерированный код должен обращаться со строковыми полями. Это заменяет опцию ctype из proto2 и proto3 и предлагает новую функцию string_type. В Редакции 2023 вы можете указать либо ctype, либо string_type для поля, но не обе одновременно. В Редакции 2024 опция ctype удалена.

Доступные значения:

  • VIEW: Генерирует методы доступа string_view для поля.
  • CORD: Генерирует методы доступа Cord для поля. Не поддерживается для полей расширений.
  • STRING: Генерирует методы доступа string для поля.

Применимо к следующим областям видимости: File, Field

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024VIEW
2023STRING
proto3STRING
proto2STRING

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

message Foo {
  optional string bar = 6;
  optional string baz = 7 [ctype = CORD];
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

import "google/protobuf/cpp_features.proto";

message Foo {
  string bar = 6 [features.(pb.cpp).string_type = STRING];
  string baz = 7 [features.(pb.cpp).string_type = CORD];
}

Следующий пример показывает файл proto3:

syntax = "proto3"

message Foo {
  string bar = 6;
  string baz = 7 [ctype = CORD];
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

import "google/protobuf/cpp_features.proto";

message Foo {
  string bar = 6 [features.(pb.cpp).string_type = STRING];
  string baz = 7 [features.(pb.cpp).string_type = CORD];
}

features.(pb.java).utf8_validation

Языки: Java

Эта специфичная для языка функция позволяет переопределить настройки на уровне файла на уровне поля только для Java.

Эта функция не влияет на файлы proto3, и поэтому в этом разделе нет примеров "до" и "после" для файла proto3.

Доступные значения:

  • DEFAULT: Поведение соответствует установленному features.utf8_validation.
  • VERIFY: Переопределяет настройку features.utf8_validation на уровне файла, чтобы принудительно установить ее в VERIFY только для Java.

Применимо к следующим областям видимости: Field, File

Добавлено в: Редакция 2023

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024DEFAULT
2023DEFAULT
proto3DEFAULT
proto2DEFAULT

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Следующий пример кода показывает файл proto2:

syntax = "proto2";

option java_string_check_utf8=true;

message MyMessage {
  string foo = 1;
  string bar = 2;
}

После запуска Prototiller эквивалентный код может выглядеть так:

edition = "2024";

import "google/protobuf/java_features.proto";

option features.utf8_validation = NONE;
option features.(pb.java).utf8_validation = VERIFY;
message MyMessage {
  string foo = 1;
  string bar = 2;
}

features.(pb.go).strip_enum_prefix

Языки: Go

Значения перечислений не ограничены областью видимости их содержащего имени перечисления, поэтому рекомендуется добавлять префикс каждого значения именем перечисления:

edition = "2024";

enum Strip {
  STRIP_ZERO = 0;
  STRIP_ONE = 1;
}

Однако сгенерированный код Go теперь будет содержать два префикса!

type Strip int32

const (
    Strip_STRIP_ZERO Strip = 0
    Strip_STRIP_ONE  Strip = 1
)

Специфичная для языка функция strip_enum_prefix определяет, будет ли генератор кода Go удалять повторяющийся префикс или нет.

Доступные значения:

  • STRIP_ENUM_PREFIX_KEEP: Сохранять имя как есть, даже если оно повторяющееся.
  • STRIP_ENUM_PREFIX_GENERATE_BOTH: Генерировать оба, полное имя и сокращенное имя (чтобы помочь с миграцией вашего кода Go).
  • STRIP_ENUM_PREFIX_STRIP: Удалять префикс имени перечисления из имен значений перечисления.

Применимо к следующим областям видимости: Enum, File

Добавлено в: Редакция 2024

Поведение по умолчанию для синтаксиса/редакции:

Синтаксис/редакцияПо умолчанию
2024STRIP_ENUM_PREFIX_KEEP

Примечание: Настройки функций на разных элементах схемы имеют разные области видимости.

Вы можете установить функцию strip_enum_prefix в файлах .proto редакции 2024 (или новее):

edition = "2024";

import "google/protobuf/go_features.proto";

option features.(pb.go).strip_enum_prefix = STRIP_ENUM_PREFIX_STRIP;

enum Strip {
  STRIP_ZERO = 0;
  STRIP_ONE = 1;
}

Сгенерированный код Go теперь будет удалять префикс STRIP:

type Strip int32

const (
    Strip_ZERO Strip = 0
    Strip_ONE  Strip = 1
)

Сохранение поведения Proto2 или Proto3 в Редакции 2023

Вы можете захотеть перейти на формат редакций, но еще не разбираться с обновлениями в способе поведения сгенерированного кода. Этот раздел показывает изменения, которые инструмент Prototiller вносит в ваши .proto файлы, чтобы заставить protobuf на основе редакции 2023 вести себя как файл proto2 или proto3.

После того как эти изменения сделаны на уровне файла, вы получаете значения по умолчанию proto2 или proto3. Вы можете переопределить на более низких уровнях (уровень сообщения, уровень поля), чтобы учесть дополнительные различия в поведении (такие как required, proto3 optional) или если вы хотите, чтобы ваше определение было почти как proto2 или proto3.

Мы рекомендуем использовать Prototiller, если у вас нет конкретной причины не делать этого. Чтобы вручную применить все это вместо использования Prototiller, добавьте содержимое из следующих разделов в начало вашего .proto файла.

Поведение Proto2

Следующее показывает настройки для воспроизведения поведения proto2 с Редакцией 2023.

edition = "2023";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

option features.field_presence = EXPLICIT;
option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED;
option features.json_format = LEGACY_BEST_EFFORT;
option features.utf8_validation = NONE;
option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.java).legacy_closed_enum = true;

Поведение Proto3

Следующее показывает настройки для воспроизведения поведения proto3 с Редакцией 2023.

edition = "2023";

import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";

option features.field_presence = IMPLICIT;
option features.enum_type = OPEN;
// `packed=false` необходимо преобразовать в функции repeated_field_encoding на уровне поля
// в синтаксисе Редакций
option features.json_format = ALLOW;
option features.utf8_validation = VERIFY;
option features.(pb.cpp).legacy_closed_enum = false;
option features.(pb.java).legacy_closed_enum = false;

Редакция 2023 к 2024

Следующее показывает настройки для воспроизведения поведения Редакции 2023 с Редакцией 2024.

// foo/bar_baz.proto
edition = "2024";

import option "third_party/protobuf/cpp_features.proto";
import option "third_party/java/protobuf/java_features.proto";
import option "third_party/golang/protobuf/v2/src/google/protobuf/go_features.proto";

// Если ранее полагались на значение по умолчанию java_outer_classname редакции 2023.
option java_outer_classname = "BarBaz" // или BarBazOuterClass

option features.(pb.cpp).string_type = STRING;
option features.enforce_naming_style = STYLE_LEGACY;
option features.default_symbol_visibility = EXPORT_ALL;
option features.(pb.cpp).enum_name_uses_string_view = false;
option features.(pb.go).api_level = API_OPEN;

message MyMessage {
  option features.(pb.java).nest_in_file_class = YES;
}

Предостережения и исключения

Этот раздел показывает изменения, которые вам нужно будет сделать вручную, если вы решите не использовать Prototiller.

Установка значений по умолчанию на уровне файла, показанных в предыдущем разделе, устанавливает поведение по умолчанию в большинстве случаев, но есть несколько исключений.

Редакция 2023 и позже

  • optional: Удалите все экземпляры метки optional и измените features.field_presence на EXPLICIT, если значение по умолчанию для файла — IMPLICIT.
  • required: Удалите все экземпляры метки required и добавьте опцию features.field_presence=LEGACY_REQUIRED на уровне поля.
  • groups: Разверните groups в отдельное сообщение и добавьте опцию features.message_encoding = DELIMITED на уровне поля. См. features.message_encoding для получения дополнительной информации об этом.
  • java_string_check_utf8: Удалите эту опцию файла и замените ее на features.(pb.java).utf8_validation. Вам нужно будет импортировать функции Java, как описано в Специфичные для языка функции.
  • packed: Для файлов proto2, преобразованных в формат редакций, удалите опцию поля packed и добавьте [features.repeated_field_encoding=PACKED] на уровне поля, когда вы не хотите поведения EXPANDED, которое вы установили в Поведение Proto2. Для файлов proto3, преобразованных в формат редакций, добавьте [features.repeated_field_encoding=EXPANDED] на уровне поля, когда вы не хотите поведения по умолчанию для proto3.

Редакция 2024 и позже

  • (C++) ctype: Удалите все экземпляры опции ctype и установите значение features.(pb.cpp).string_type.
  • (C++ и Go) weak: Удалите слабый импорт. Используйте import option вместо этого.
  • (Java) java_multiple_files: Удалите java_multiple_files и используйте features.(pb.java).nest_in_file_class вместо этого.