Skip to content

Commit 8667063

Browse files
Document enum allow_aliasing behavior for ProtoJSON and TextFormat.
PiperOrigin-RevId: 931100746
1 parent 2d0d946 commit 8667063

2 files changed

Lines changed: 94 additions & 7 deletions

File tree

content/programming-guides/json.md

Lines changed: 82 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,9 @@ The following table shows how data is represented in JSON files.
8282
<td>string</td>
8383
<td><code>"FOO_BAR"</code></td>
8484
<td>The name of the enum value as specified in proto is used. Parsers
85-
accept both enum names and integer values.
85+
accept both enum names and integer values. See
86+
<a href="#enum-aliasing">Enum Aliasing</a> for details on enums with
87+
aliases.
8688
</td>
8789
</tr>
8890
<tr>
@@ -359,6 +361,85 @@ JSON when prioritizing interoperability, including:
359361
documentation recommends using a JSON string instead of a number when
360362
precision beyond 2**53 is desired.
361363

364+
## Enum Aliasing {#enum-aliasing}
365+
366+
When an enum definition has `option allow_aliasing = true;`, multiple enum
367+
constant names can map to the same numeric value.
368+
369+
### Serialization Behavior
370+
371+
Serializers **must** print the first listed name in the enum definition for a
372+
given numeric value.
373+
374+
For example, given:
375+
376+
```proto
377+
enum MyEnum {
378+
option allow_alias = true;
379+
UNKNOWN = 0;
380+
OLD_NAME = 1;
381+
NEW_NAME = 1;
382+
}
383+
```
384+
385+
If the value is `1`, the serializer will output `"OLD_NAME"`.
386+
387+
### Parsing Behavior
388+
389+
Parsers **must** accept any of the names defined for that numeric value. In the
390+
example above, the parser will accept both `"OLD_NAME"` and `"NEW_NAME"` as
391+
mapping to value `1`.
392+
393+
### Safe Renaming Strategy {#safe-renaming}
394+
395+
This behavior enables a safe, multi-step migration path for renaming enum values
396+
in a distributed system:
397+
398+
1. **Add the new name as an alias:** Add the new name below the old name,
399+
mapping to the same value.
400+
401+
```proto
402+
enum MyEnum {
403+
option allow_aliasing = true;
404+
UNKNOWN = 0;
405+
OLD_NAME = 1;
406+
NEW_NAME = 1; // New name added as alias
407+
}
408+
```
409+
410+
2. **Deploy the schema:** Deploy this schema to all systems. At this point, all
411+
parsers will recognize both `OLD_NAME` and `NEW_NAME`, but all serializers
412+
will still emit `OLD_NAME` (since it is listed first).
413+
414+
3. **Swap the order:** Swap the order of the aliases in the proto file.
415+
416+
```proto
417+
enum MyEnum {
418+
option allow_aliasing = true;
419+
UNKNOWN = 0;
420+
NEW_NAME = 1; // New name is now first
421+
OLD_NAME = 1;
422+
}
423+
```
424+
425+
4. **Deploy the schema:** Deploy this updated schema. Now, serializers will
426+
begin emitting `NEW_NAME`. Parsers will still accept both names, ensuring
427+
that any systems still running the previous version of the schema can safely
428+
parse the new name.
429+
430+
5. **Remove the old name:** Once all systems have been updated and you are sure
431+
no old serialized data remains that needs to be parsed by a system that
432+
might be rolled back, you can safely remove the old name.
433+
434+
```proto
435+
enum MyEnum {
436+
UNKNOWN = 0;
437+
NEW_NAME = 1;
438+
}
439+
```
440+
441+
This semantic also matches TextProto for the same reason.
442+
362443
## Any {#any}
363444
364445
### Normal messages {#any-normal-messages}

content/reference/protobuf/textformat-spec.md

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -360,8 +360,8 @@ messages: [{}, {}] # Valid
360360
messages [{}, {}] # Valid
361361
```
362362

363-
Values of message fields can be surrounded by curly brackets
364-
or angle brackets:
363+
Values of message fields can be surrounded by curly
364+
brackets or angle brackets:
365365

366366
```textproto
367367
message: { foo: "bar" }
@@ -524,6 +524,12 @@ integer = signedInteger | unsignedInteger ;
524524
issue a warning when a provided number value is not a valid member. Note
525525
that certain names that are valid keywords in other contexts, such as
526526
<em>"true"</em> or <em>"infinity"</em>, are also valid enum value names.
527+
<p>
528+
For enums with <code>allow_aliasing</code>, serializers must print the
529+
first listed name for a given numeric value, and parsers must accept
530+
any of the names. This enables a safe renaming strategy similar to the one
531+
described in the <a href="/programming-guides/json#enum-aliasing">ProtoJSON enum aliasing documentation</a>.
532+
</p>
527533
</td>
528534
</tr>
529535
<tr>
@@ -723,8 +729,8 @@ support. Some tooling also
723729
supports the legacy extensions `.textpb` and `.pbtxt`. All other extensions
724730
besides the above are **strongly** discouraged; in particular, extensions such
725731
as `.protoascii` wrongly imply that text format is ascii-only, and others like
726-
`.pb.txt` are not recognized by common tooling.
727-
{{% /alert %}}
732+
`.pb.txt` are not recognized by common
733+
tooling. {{% /alert %}}
728734

729735
```textproto
730736
# This is an example of Protocol Buffer's text format.
@@ -760,8 +766,8 @@ the schema, so they may provide various features.
760766

761767
## Working with the Format Programmatically
762768

763-
Due to how individual Protocol Buffer implementations emit
764-
neither a consistent nor canonical text format,
769+
Due to how individual Protocol Buffer implementations
770+
emit neither a consistent nor canonical text format,
765771
tools or libraries that modify TextProto files or emit TextProto output must
766772
explicitly use
767773
https://github.com/protocolbuffers/txtpbfmt

0 commit comments

Comments
 (0)