xref: /aosp_15_r20/external/protobuf/docs/field_presence.md (revision 1b3f573f81763fcece89efc2b6a5209149e44ab8)
1*1b3f573fSAndroid Build Coastguard Worker# Application note: Field presence
2*1b3f573fSAndroid Build Coastguard Worker
3*1b3f573fSAndroid Build Coastguard WorkerThis application note explains the various presence tracking disciplines for protobuf fields. It also explains the behaviour of explicit presence tracking for singular proto3 fields with basic types.
4*1b3f573fSAndroid Build Coastguard Worker
5*1b3f573fSAndroid Build Coastguard Worker## Background
6*1b3f573fSAndroid Build Coastguard Worker
7*1b3f573fSAndroid Build Coastguard Worker_Field presence_ is the notion of whether a protobuf field has a value. There are two different manifestations of presence for protobufs: _no presence_, where the generated message API stores field values (only), and _explicit presence_, where the API also stores whether or not a field has been set.
8*1b3f573fSAndroid Build Coastguard Worker
9*1b3f573fSAndroid Build Coastguard WorkerHistorically, proto2 has mostly followed _explicit presence_, while proto3 exposes only _no presence_ semantics. Singular proto3 fields of basic types (numeric, string, bytes, and enums) which are defined with the `optional` label have _explicit presence_, like proto2 (this feature is enabled by default as release 3.15).
10*1b3f573fSAndroid Build Coastguard Worker
11*1b3f573fSAndroid Build Coastguard Worker### Presence disciplines
12*1b3f573fSAndroid Build Coastguard Worker
13*1b3f573fSAndroid Build Coastguard Worker_Presence disciplines_ define the semantics for translating between the _API representation_ and the _serialized representation_. The _no presence_ discipline relies upon the field value itself to make decisions at (de)serialization time, while the _explicit presence_ discipline relies upon the explicit tracking state instead.
14*1b3f573fSAndroid Build Coastguard Worker
15*1b3f573fSAndroid Build Coastguard Worker### Presence in _tag-value stream_ (wire format) serialization
16*1b3f573fSAndroid Build Coastguard Worker
17*1b3f573fSAndroid Build Coastguard WorkerThe wire format is a stream of tagged, _self-delimiting_ values. By definition, the wire format represents a sequence of _present_ values. In other words, every value found within a serialization represents a _present_ field; furthermore, the serialization contains no information about not-present values.
18*1b3f573fSAndroid Build Coastguard Worker
19*1b3f573fSAndroid Build Coastguard WorkerThe generated API for a proto message includes (de)serialization definitions which translate between API types and a stream of definitionally _present_ (tag, value) pairs. This translation is designed to be forward- and backward-compatible across changes to the message definition; however, this compatibility introduces some (perhaps surprising) considerations when deserializing wire-formatted messages:
20*1b3f573fSAndroid Build Coastguard Worker
21*1b3f573fSAndroid Build Coastguard Worker-   When serializing, fields with _no presence_ are not serialized if they contain their default value.
22*1b3f573fSAndroid Build Coastguard Worker	-   For numeric types, the default is 0.
23*1b3f573fSAndroid Build Coastguard Worker	-   For enums, the default is the zero-valued enumerator.
24*1b3f573fSAndroid Build Coastguard Worker	-   For strings, bytes, and repeated fields, the default is the zero-length value.
25*1b3f573fSAndroid Build Coastguard Worker	-   For messages, the default is the language-specific null value.
26*1b3f573fSAndroid Build Coastguard Worker-   "Empty" length-delimited values (such as empty strings) can be validly represented in serialized values: the field is "present," in the sense that it appears in the wire format. However, if the generated API does not track presence, then these values may not be re-serialized; i.e., the empty field may be "not present" after a serialization round-trip.
27*1b3f573fSAndroid Build Coastguard Worker-   When deserializing, duplicate field values may be handled in different ways depending on the field definition.
28*1b3f573fSAndroid Build Coastguard Worker	-   Duplicate `repeated` fields are typically appended to the field's API representation. (Note that serializing a _packed_ repeated field produces only one, length-delimited value in the tag stream.)
29*1b3f573fSAndroid Build Coastguard Worker	-   Duplicate `optional` field values follow the rule that "the last one wins."
30*1b3f573fSAndroid Build Coastguard Worker-   `oneof` fields expose the API-level invariant that only one field is set at a time. However, the wire format may include multiple (tag, value) pairs which notionally belong to the `oneof`. Similar to `optional` fields, the generated API follows the "last one wins" rule.
31*1b3f573fSAndroid Build Coastguard Worker-   Out-of-range values are not returned for enum fields in generated proto2 APIs. However, out-of-range values may be stored as _unknown fields_ in the API, even though the wire-format tag was recognized.
32*1b3f573fSAndroid Build Coastguard Worker
33*1b3f573fSAndroid Build Coastguard Worker### Presence in _named-field mapping_ formats
34*1b3f573fSAndroid Build Coastguard Worker
35*1b3f573fSAndroid Build Coastguard WorkerProtobufs can be represented in human-readable, textual forms. Two notable formats are TextFormat (the output format produced by generated message `DebugString` methods) and JSON.
36*1b3f573fSAndroid Build Coastguard Worker
37*1b3f573fSAndroid Build Coastguard WorkerThese formats have correctness requirements of their own, and are generally stricter than _tagged-value stream_ formats. However, TextFormat more closely mimics the semantics of the wire format, and does, in certain cases, provide similar semantics (for example, appending repeated name-value mappings to a repeated field). In particular, similar to the wire format, TextFormat only includes fields which are present.
38*1b3f573fSAndroid Build Coastguard Worker
39*1b3f573fSAndroid Build Coastguard WorkerJSON is a much stricter format, however, and cannot validly represent some semantics of the wire format or TextFormat.
40*1b3f573fSAndroid Build Coastguard Worker
41*1b3f573fSAndroid Build Coastguard Worker-   Notably, JSON _elements_ are semantically unordered, and each member must have a unique name. This is different from TextFormat rules for repeated fields.
42*1b3f573fSAndroid Build Coastguard Worker-   JSON may include fields that are "not present," unlike the _no presence_ discipline for other formats:
43*1b3f573fSAndroid Build Coastguard Worker	-   JSON defines a `null` value, which may be used to represent a _defined but not-present field_.
44*1b3f573fSAndroid Build Coastguard Worker	-   Repeated field values may be included in the formatted output, even if they are equal to the default (an empty list).
45*1b3f573fSAndroid Build Coastguard Worker-   Because JSON elements are unordered, there is no way to unambiguously interpret the "last one wins" rule.
46*1b3f573fSAndroid Build Coastguard Worker    -   In most cases, this is fine: JSON elements must have unique names: repeated field values are not valid JSON, so they do not need to be resolved as they are for TextFormat.
47*1b3f573fSAndroid Build Coastguard Worker	-   However, this means that it may not be possible to interpret `oneof` fields unambiguously: if multiple cases are present, they are unordered.
48*1b3f573fSAndroid Build Coastguard Worker
49*1b3f573fSAndroid Build Coastguard WorkerIn theory, JSON _can_ represent presence in a semantic-preserving fashion. In practice, however, presence correctness can vary depending upon implementation choices, especially if JSON was chosen as a means to interoperate with clients not using protobufs.
50*1b3f573fSAndroid Build Coastguard Worker
51*1b3f573fSAndroid Build Coastguard Worker### Presence in proto2 APIs
52*1b3f573fSAndroid Build Coastguard Worker
53*1b3f573fSAndroid Build Coastguard WorkerThis table outlines whether presence is tracked for fields in proto2 APIs (both for generated APIs and using dynamic reflection):
54*1b3f573fSAndroid Build Coastguard Worker
55*1b3f573fSAndroid Build Coastguard WorkerField type                                   | Explicit Presence
56*1b3f573fSAndroid Build Coastguard Worker-------------------------------------------- | -----------------
57*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | ✔️
58*1b3f573fSAndroid Build Coastguard WorkerSingular enum                                | ✔️
59*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes                     | ✔️
60*1b3f573fSAndroid Build Coastguard WorkerSingular message                             | ✔️
61*1b3f573fSAndroid Build Coastguard WorkerRepeated                                     |
62*1b3f573fSAndroid Build Coastguard WorkerOneofs                                       | ✔️
63*1b3f573fSAndroid Build Coastguard WorkerMaps                                         |
64*1b3f573fSAndroid Build Coastguard Worker
65*1b3f573fSAndroid Build Coastguard WorkerSingular fields (of all types) track presence explicitly in the generated API. The generated message interface includes methods to query presence of fields. For example, the field `foo` has a corresponding `has_foo` method. (The specific name follows the same language-specific naming convention as the field accessors.) These methods are sometimes referred to as "hazzers" within the protobuf implementation.
66*1b3f573fSAndroid Build Coastguard Worker
67*1b3f573fSAndroid Build Coastguard WorkerSimilar to singular fields, `oneof` fields explicitly track which one of the members, if any, contains a value. For example, consider this example `oneof`:
68*1b3f573fSAndroid Build Coastguard Worker
69*1b3f573fSAndroid Build Coastguard Worker```protobuf
70*1b3f573fSAndroid Build Coastguard Workeroneof foo {
71*1b3f573fSAndroid Build Coastguard Worker  int32 a = 1;
72*1b3f573fSAndroid Build Coastguard Worker  float b = 2;
73*1b3f573fSAndroid Build Coastguard Worker}
74*1b3f573fSAndroid Build Coastguard Worker```
75*1b3f573fSAndroid Build Coastguard Worker
76*1b3f573fSAndroid Build Coastguard WorkerDepending on the target language, the generated API would generally include several methods:
77*1b3f573fSAndroid Build Coastguard Worker
78*1b3f573fSAndroid Build Coastguard Worker-   A hazzer for the oneof: `has_foo`
79*1b3f573fSAndroid Build Coastguard Worker-   A _oneof case_ method: `foo`
80*1b3f573fSAndroid Build Coastguard Worker-   Hazzers for the members: `has_a`, `has_b`
81*1b3f573fSAndroid Build Coastguard Worker-   Getters for the members: `a`, `b`
82*1b3f573fSAndroid Build Coastguard Worker
83*1b3f573fSAndroid Build Coastguard WorkerRepeated fields and maps do not track presence: there is no distinction between an _empty_ and a _not-present_ repeated field.
84*1b3f573fSAndroid Build Coastguard Worker
85*1b3f573fSAndroid Build Coastguard Worker### Presence in proto3 APIs
86*1b3f573fSAndroid Build Coastguard Worker
87*1b3f573fSAndroid Build Coastguard WorkerThis table outlines whether presence is tracked for fields in proto3 APIs (both for generated APIs and using dynamic reflection):
88*1b3f573fSAndroid Build Coastguard Worker
89*1b3f573fSAndroid Build Coastguard WorkerField type                                   | `optional` | Explicit Presence
90*1b3f573fSAndroid Build Coastguard Worker-------------------------------------------- | ---------- | -----------------
91*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | No         |
92*1b3f573fSAndroid Build Coastguard WorkerSingular enum                                | No         |
93*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes                     | No         |
94*1b3f573fSAndroid Build Coastguard WorkerSingular numeric (integer or floating point) | Yes        | ✔️
95*1b3f573fSAndroid Build Coastguard WorkerSingular enum                                | Yes        | ✔️
96*1b3f573fSAndroid Build Coastguard WorkerSingular string or bytes                     | Yes        | ✔️
97*1b3f573fSAndroid Build Coastguard WorkerSingular message                             | Yes        | ✔️
98*1b3f573fSAndroid Build Coastguard WorkerSingular message                             | No         | ✔️
99*1b3f573fSAndroid Build Coastguard WorkerRepeated                                     | N/A        |
100*1b3f573fSAndroid Build Coastguard WorkerOneofs                                       | N/A        | ✔️
101*1b3f573fSAndroid Build Coastguard WorkerMaps                                         | N/A        |
102*1b3f573fSAndroid Build Coastguard Worker
103*1b3f573fSAndroid Build Coastguard WorkerSimilar to proto2 APIs, proto3 does not track presence explicitly for repeated fields. Without the `optional` label, proto3 APIs do not track presence for basic types (numeric, string, bytes, and enums), either. Oneof fields affirmatively expose presence, although the same set of hazzer methods may not generated as in proto2 APIs.
104*1b3f573fSAndroid Build Coastguard Worker
105*1b3f573fSAndroid Build Coastguard WorkerUnder the _no presence_ discipline, the default value is synonymous with "not present" for purposes of serialization. To notionally "clear" a field (so it won't be serialized), an API user would set it to the default value.
106*1b3f573fSAndroid Build Coastguard Worker
107*1b3f573fSAndroid Build Coastguard WorkerThe default value for enum-typed fields under _no presence_ is the corresponding 0-valued enumerator. Under proto3 syntax rules, all enum types are required to have an enumerator value which maps to 0. By convention, this is an `UNKNOWN` or similarly-named enumerator. If the zero value is notionally outside the domain of valid values for the application, this behavior can be thought of as tantamount to _explicit presence_.
108*1b3f573fSAndroid Build Coastguard Worker
109*1b3f573fSAndroid Build Coastguard Worker## Semantic differences
110*1b3f573fSAndroid Build Coastguard Worker
111*1b3f573fSAndroid Build Coastguard WorkerThe _no presence_ serialization discipline results in visible differences from the _explicit presence_ tracking discipline, when the default value is set. For a singular field with numeric, enum, or string type:
112*1b3f573fSAndroid Build Coastguard Worker
113*1b3f573fSAndroid Build Coastguard Worker-   _No presence_ discipline:
114*1b3f573fSAndroid Build Coastguard Worker	-   Default values are not serialized.
115*1b3f573fSAndroid Build Coastguard Worker	-   Default values are _not_ merged-from.
116*1b3f573fSAndroid Build Coastguard Worker	-   To "clear" a field, it is set to its default value.
117*1b3f573fSAndroid Build Coastguard Worker    -   The default value may mean:
118*1b3f573fSAndroid Build Coastguard Worker		-   the field was explicitly set to its default value, which is valid in the application-specific domain of values;
119*1b3f573fSAndroid Build Coastguard Worker		-   the field was notionally "cleared" by setting its default; or
120*1b3f573fSAndroid Build Coastguard Worker		-   the field was never set.
121*1b3f573fSAndroid Build Coastguard Worker-   _Explicit presence_ discipline:
122*1b3f573fSAndroid Build Coastguard Worker	-   Explicitly set values are always serialized, including default values.
123*1b3f573fSAndroid Build Coastguard Worker	-   Un-set fields are never merged-from.
124*1b3f573fSAndroid Build Coastguard Worker	-   Explicitly set fields -- including default values -- _are_ merged-from.
125*1b3f573fSAndroid Build Coastguard Worker	-   A generated `has_foo` method indicates whether or not the field `foo` has been set (and not cleared).
126*1b3f573fSAndroid Build Coastguard Worker	-   A generated `clear_foo` method must be used to clear (i.e., un-set) the value.
127*1b3f573fSAndroid Build Coastguard Worker
128*1b3f573fSAndroid Build Coastguard Worker### Considerations for merging
129*1b3f573fSAndroid Build Coastguard Worker
130*1b3f573fSAndroid Build Coastguard WorkerUnder the _no presence_ rules, it is effectively impossible for a target field to merge-from its default value (using the protobuf's API merging functions). This is because default values are skipped, similar to the _no presence_ serialization discipline. Merging only updates the target (merged-to) message using the non-skipped values from the update (merged-from) message.
131*1b3f573fSAndroid Build Coastguard Worker
132*1b3f573fSAndroid Build Coastguard WorkerThe difference in merging behavior has further implications for protocols which rely on partial "patch" updates. If field presence is not tracked, then an update patch alone cannot represent an update to the default value, because only non-default values are merged-from.
133*1b3f573fSAndroid Build Coastguard Worker
134*1b3f573fSAndroid Build Coastguard WorkerUpdating to set a default value in this case requires some external mechanism, such as `FieldMask`. However, if presence _is_ tracked, then all explicitly-set values -- even default values -- will be merged into the target.
135*1b3f573fSAndroid Build Coastguard Worker
136*1b3f573fSAndroid Build Coastguard Worker### Considerations for change-compatibility
137*1b3f573fSAndroid Build Coastguard Worker
138*1b3f573fSAndroid Build Coastguard WorkerChanging a field between _explicit presence_ and _no presence_ is a binary-compatible change for serialized values in wire format. However, the serialized representation of the message may differ, depending on which version of the message definition was used for serialization. Specifically, when a "sender" explicitly sets a field to its default value:
139*1b3f573fSAndroid Build Coastguard Worker
140*1b3f573fSAndroid Build Coastguard Worker-   The serialized value following _no presence_ discipline does not contain the default value, even though it was explicitly set.
141*1b3f573fSAndroid Build Coastguard Worker-   The serialized value following _explicit presence_ discipline contains every "present" field, even if it contains the default value.
142*1b3f573fSAndroid Build Coastguard Worker
143*1b3f573fSAndroid Build Coastguard WorkerThis change may or may not be safe, depending on the application's semantics. For example, consider two clients with different versions of a message definition.
144*1b3f573fSAndroid Build Coastguard Worker
145*1b3f573fSAndroid Build Coastguard WorkerClient A uses this definition of the message, which follows the _explicit presence_ serialization discipline for field `foo`:
146*1b3f573fSAndroid Build Coastguard Worker
147*1b3f573fSAndroid Build Coastguard Worker```protobuf
148*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3";
149*1b3f573fSAndroid Build Coastguard Workermessage Msg {
150*1b3f573fSAndroid Build Coastguard Worker  optional int32 foo = 1;
151*1b3f573fSAndroid Build Coastguard Worker}
152*1b3f573fSAndroid Build Coastguard Worker```
153*1b3f573fSAndroid Build Coastguard Worker
154*1b3f573fSAndroid Build Coastguard WorkerClient B uses a definition of the same message, except that it follows the _no presence_ discipline:
155*1b3f573fSAndroid Build Coastguard Worker
156*1b3f573fSAndroid Build Coastguard Worker```protobuf
157*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3";
158*1b3f573fSAndroid Build Coastguard Workermessage Msg {
159*1b3f573fSAndroid Build Coastguard Worker  int32 foo = 1;
160*1b3f573fSAndroid Build Coastguard Worker}
161*1b3f573fSAndroid Build Coastguard Worker```
162*1b3f573fSAndroid Build Coastguard Worker
163*1b3f573fSAndroid Build Coastguard WorkerNow, consider a scenario where client A observes `foo`'s presence as the clients repeatedly exchange the "same" message by deserializing and reserializing:
164*1b3f573fSAndroid Build Coastguard Worker
165*1b3f573fSAndroid Build Coastguard Worker```protobuf
166*1b3f573fSAndroid Build Coastguard Worker// Client A:
167*1b3f573fSAndroid Build Coastguard WorkerMsg m_a;
168*1b3f573fSAndroid Build Coastguard Workerm_a.set_foo(1);                  // non-default value
169*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo());           // OK
170*1b3f573fSAndroid Build Coastguard WorkerSend(m_a.SerializeAsString());   // to client B
171*1b3f573fSAndroid Build Coastguard Worker
172*1b3f573fSAndroid Build Coastguard Worker// Client B:
173*1b3f573fSAndroid Build Coastguard WorkerMsg m_b;
174*1b3f573fSAndroid Build Coastguard Workerm_b.ParseFromString(Receive());  // from client A
175*1b3f573fSAndroid Build Coastguard Workerassert(m_b.foo() == 1);          // OK
176*1b3f573fSAndroid Build Coastguard WorkerSend(m_b.SerializeAsString());   // to client A
177*1b3f573fSAndroid Build Coastguard Worker
178*1b3f573fSAndroid Build Coastguard Worker// Client A:
179*1b3f573fSAndroid Build Coastguard Workerm_a.ParseFromString(Receive());  // from client B
180*1b3f573fSAndroid Build Coastguard Workerassert(m_a.foo() == 1);          // OK
181*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo());           // OK
182*1b3f573fSAndroid Build Coastguard Workerm_a.set_foo(0);                  // default value
183*1b3f573fSAndroid Build Coastguard WorkerSend(m_a.SerializeAsString());   // to client B
184*1b3f573fSAndroid Build Coastguard Worker
185*1b3f573fSAndroid Build Coastguard Worker// Client B:
186*1b3f573fSAndroid Build Coastguard WorkerMsg m_b;
187*1b3f573fSAndroid Build Coastguard Workerm_b.ParseFromString(Receive());  // from client A
188*1b3f573fSAndroid Build Coastguard Workerassert(m_b.foo() == 0);          // OK
189*1b3f573fSAndroid Build Coastguard WorkerSend(m_b.SerializeAsString());   // to client A
190*1b3f573fSAndroid Build Coastguard Worker
191*1b3f573fSAndroid Build Coastguard Worker// Client A:
192*1b3f573fSAndroid Build Coastguard Workerm_a.ParseFromString(Receive());  // from client B
193*1b3f573fSAndroid Build Coastguard Workerassert(m_a.foo() == 0);          // OK
194*1b3f573fSAndroid Build Coastguard Workerassert(m_a.has_foo());           // FAIL
195*1b3f573fSAndroid Build Coastguard Worker```
196*1b3f573fSAndroid Build Coastguard Worker
197*1b3f573fSAndroid Build Coastguard WorkerIf client A depends on _explicit presence_ for `foo`, then a "round trip" through client B will be lossy from the perspective of client A. In the example, this is not a safe change: client A requires (by `assert`) that the field is present; even without any modifications through the API, that requirement fails in a value- and peer-dependent case.
198*1b3f573fSAndroid Build Coastguard Worker
199*1b3f573fSAndroid Build Coastguard Worker## How to enable _explicit presence_ in proto3
200*1b3f573fSAndroid Build Coastguard Worker
201*1b3f573fSAndroid Build Coastguard WorkerThese are the general steps to use field tracking support for proto3:
202*1b3f573fSAndroid Build Coastguard Worker
203*1b3f573fSAndroid Build Coastguard Worker1.  Add an `optional` field to a `.proto` file.
204*1b3f573fSAndroid Build Coastguard Worker1.  Run `protoc` (at least v3.15, or v3.12 using `--experimental_allow_proto3_optional` flag).
205*1b3f573fSAndroid Build Coastguard Worker1.  Use the generated "hazzer" methods and "clear" methods in application code, instead of comparing or setting default values.
206*1b3f573fSAndroid Build Coastguard Worker
207*1b3f573fSAndroid Build Coastguard Worker### `.proto` file changes
208*1b3f573fSAndroid Build Coastguard Worker
209*1b3f573fSAndroid Build Coastguard WorkerThis is an example of a proto3 message with fields which follow both _no presence_ and _explicit presence_ semantics:
210*1b3f573fSAndroid Build Coastguard Worker
211*1b3f573fSAndroid Build Coastguard Worker```protobuf
212*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3";
213*1b3f573fSAndroid Build Coastguard Workerpackage example;
214*1b3f573fSAndroid Build Coastguard Worker
215*1b3f573fSAndroid Build Coastguard Workermessage MyMessage {
216*1b3f573fSAndroid Build Coastguard Worker  // No presence:
217*1b3f573fSAndroid Build Coastguard Worker  int32 not_tracked = 1;
218*1b3f573fSAndroid Build Coastguard Worker
219*1b3f573fSAndroid Build Coastguard Worker  // Explicit presence:
220*1b3f573fSAndroid Build Coastguard Worker  optional int32 tracked = 2;
221*1b3f573fSAndroid Build Coastguard Worker}
222*1b3f573fSAndroid Build Coastguard Worker```
223*1b3f573fSAndroid Build Coastguard Worker
224*1b3f573fSAndroid Build Coastguard Worker### `protoc` invocation
225*1b3f573fSAndroid Build Coastguard Worker
226*1b3f573fSAndroid Build Coastguard WorkerPresence tracking for proto3 messages is enabled by default [since v3.15.0](https://github.com/protocolbuffers/protobuf/releases/tag/v3.15.0) release, formerly up until [v3.12.0](https://github.com/protocolbuffers/protobuf/releases/tag/v3.12.0) the `--experimental_allow_proto3_optional` flag was required when using presence tracking with protoc.
227*1b3f573fSAndroid Build Coastguard Worker
228*1b3f573fSAndroid Build Coastguard Worker### Using the generated code
229*1b3f573fSAndroid Build Coastguard Worker
230*1b3f573fSAndroid Build Coastguard WorkerThe generated code for proto3 fields with _explicit presence_ (the `optional` label) will be the same as it would be in a proto2 file.
231*1b3f573fSAndroid Build Coastguard Worker
232*1b3f573fSAndroid Build Coastguard WorkerThis is the definition used in the "no presence" examples below:
233*1b3f573fSAndroid Build Coastguard Worker
234*1b3f573fSAndroid Build Coastguard Worker```protobuf
235*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3";
236*1b3f573fSAndroid Build Coastguard Workerpackage example;
237*1b3f573fSAndroid Build Coastguard Workermessage Msg {
238*1b3f573fSAndroid Build Coastguard Worker  int32 foo = 1;
239*1b3f573fSAndroid Build Coastguard Worker}
240*1b3f573fSAndroid Build Coastguard Worker```
241*1b3f573fSAndroid Build Coastguard Worker
242*1b3f573fSAndroid Build Coastguard WorkerThis is the definition used in the "explicit presence" examples below:
243*1b3f573fSAndroid Build Coastguard Worker
244*1b3f573fSAndroid Build Coastguard Worker```protobuf
245*1b3f573fSAndroid Build Coastguard Workersyntax = "proto3";
246*1b3f573fSAndroid Build Coastguard Workerpackage example;
247*1b3f573fSAndroid Build Coastguard Workermessage Msg {
248*1b3f573fSAndroid Build Coastguard Worker  optional int32 foo = 1;
249*1b3f573fSAndroid Build Coastguard Worker}
250*1b3f573fSAndroid Build Coastguard Worker```
251*1b3f573fSAndroid Build Coastguard Worker
252*1b3f573fSAndroid Build Coastguard WorkerIn the examples, a function `GetProto` constructs and returns a message of type `Msg` with unspecified contents.
253*1b3f573fSAndroid Build Coastguard Worker
254*1b3f573fSAndroid Build Coastguard Worker#### C++ example
255*1b3f573fSAndroid Build Coastguard Worker
256*1b3f573fSAndroid Build Coastguard WorkerNo presence:
257*1b3f573fSAndroid Build Coastguard Worker
258*1b3f573fSAndroid Build Coastguard Worker```C++
259*1b3f573fSAndroid Build Coastguard WorkerMsg m = GetProto();
260*1b3f573fSAndroid Build Coastguard Workerif (m.foo() != 0) {
261*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
262*1b3f573fSAndroid Build Coastguard Worker  m.set_foo(0);
263*1b3f573fSAndroid Build Coastguard Worker} else {
264*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
265*1b3f573fSAndroid Build Coastguard Worker  m.set_foo(1);
266*1b3f573fSAndroid Build Coastguard Worker}
267*1b3f573fSAndroid Build Coastguard Worker```
268*1b3f573fSAndroid Build Coastguard Worker
269*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
270*1b3f573fSAndroid Build Coastguard Worker
271*1b3f573fSAndroid Build Coastguard Worker```C++
272*1b3f573fSAndroid Build Coastguard WorkerMsg m = GetProto();
273*1b3f573fSAndroid Build Coastguard Workerif (m.has_foo()) {
274*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
275*1b3f573fSAndroid Build Coastguard Worker  m.clear_foo();
276*1b3f573fSAndroid Build Coastguard Worker} else {
277*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
278*1b3f573fSAndroid Build Coastguard Worker  m.set_foo(1);
279*1b3f573fSAndroid Build Coastguard Worker}
280*1b3f573fSAndroid Build Coastguard Worker```
281*1b3f573fSAndroid Build Coastguard Worker
282*1b3f573fSAndroid Build Coastguard Worker#### C# example
283*1b3f573fSAndroid Build Coastguard Worker
284*1b3f573fSAndroid Build Coastguard WorkerNo presence:
285*1b3f573fSAndroid Build Coastguard Worker
286*1b3f573fSAndroid Build Coastguard Worker```C#
287*1b3f573fSAndroid Build Coastguard Workervar m = GetProto();
288*1b3f573fSAndroid Build Coastguard Workerif (m.Foo != 0) {
289*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
290*1b3f573fSAndroid Build Coastguard Worker  m.Foo = 0;
291*1b3f573fSAndroid Build Coastguard Worker} else {
292*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
293*1b3f573fSAndroid Build Coastguard Worker  m.Foo = 1;
294*1b3f573fSAndroid Build Coastguard Worker}
295*1b3f573fSAndroid Build Coastguard Worker```
296*1b3f573fSAndroid Build Coastguard Worker
297*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
298*1b3f573fSAndroid Build Coastguard Worker
299*1b3f573fSAndroid Build Coastguard Worker```C#
300*1b3f573fSAndroid Build Coastguard Workervar m = GetProto();
301*1b3f573fSAndroid Build Coastguard Workerif (m.HasFoo) {
302*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
303*1b3f573fSAndroid Build Coastguard Worker  m.ClearFoo();
304*1b3f573fSAndroid Build Coastguard Worker} else {
305*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
306*1b3f573fSAndroid Build Coastguard Worker  m.Foo = 1;
307*1b3f573fSAndroid Build Coastguard Worker}
308*1b3f573fSAndroid Build Coastguard Worker```
309*1b3f573fSAndroid Build Coastguard Worker
310*1b3f573fSAndroid Build Coastguard Worker#### Go example
311*1b3f573fSAndroid Build Coastguard Worker
312*1b3f573fSAndroid Build Coastguard WorkerNo presence:
313*1b3f573fSAndroid Build Coastguard Worker
314*1b3f573fSAndroid Build Coastguard Worker```go
315*1b3f573fSAndroid Build Coastguard Workerm := GetProto()
316*1b3f573fSAndroid Build Coastguard Workerif m.Foo != 0 {
317*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
318*1b3f573fSAndroid Build Coastguard Worker  m.Foo = 0
319*1b3f573fSAndroid Build Coastguard Worker} else {
320*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
321*1b3f573fSAndroid Build Coastguard Worker  m.Foo = 1
322*1b3f573fSAndroid Build Coastguard Worker}
323*1b3f573fSAndroid Build Coastguard Worker```
324*1b3f573fSAndroid Build Coastguard Worker
325*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
326*1b3f573fSAndroid Build Coastguard Worker
327*1b3f573fSAndroid Build Coastguard Worker```go
328*1b3f573fSAndroid Build Coastguard Workerm := GetProto()
329*1b3f573fSAndroid Build Coastguard Workerif m.Foo != nil {
330*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
331*1b3f573fSAndroid Build Coastguard Worker  m.Foo = nil
332*1b3f573fSAndroid Build Coastguard Worker} else {
333*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
334*1b3f573fSAndroid Build Coastguard Worker  m.Foo = proto.Int32(1)
335*1b3f573fSAndroid Build Coastguard Worker}
336*1b3f573fSAndroid Build Coastguard Worker```
337*1b3f573fSAndroid Build Coastguard Worker
338*1b3f573fSAndroid Build Coastguard Worker#### Java example
339*1b3f573fSAndroid Build Coastguard Worker
340*1b3f573fSAndroid Build Coastguard WorkerThese examples use a `Builder` to demonstrate clearing. Simply checking presence and getting values from a `Builder` follows the same API as the message type.
341*1b3f573fSAndroid Build Coastguard Worker
342*1b3f573fSAndroid Build Coastguard WorkerNo presence:
343*1b3f573fSAndroid Build Coastguard Worker
344*1b3f573fSAndroid Build Coastguard Worker```java
345*1b3f573fSAndroid Build Coastguard WorkerMsg.Builder m = GetProto().toBuilder();
346*1b3f573fSAndroid Build Coastguard Workerif (m.getFoo() != 0) {
347*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
348*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(0);
349*1b3f573fSAndroid Build Coastguard Worker} else {
350*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
351*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(1);
352*1b3f573fSAndroid Build Coastguard Worker}
353*1b3f573fSAndroid Build Coastguard Worker```
354*1b3f573fSAndroid Build Coastguard Worker
355*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
356*1b3f573fSAndroid Build Coastguard Worker
357*1b3f573fSAndroid Build Coastguard Worker```java
358*1b3f573fSAndroid Build Coastguard WorkerMsg.Builder m = GetProto().toBuilder();
359*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) {
360*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
361*1b3f573fSAndroid Build Coastguard Worker  m.clearFoo()
362*1b3f573fSAndroid Build Coastguard Worker} else {
363*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
364*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(1);
365*1b3f573fSAndroid Build Coastguard Worker}
366*1b3f573fSAndroid Build Coastguard Worker```
367*1b3f573fSAndroid Build Coastguard Worker
368*1b3f573fSAndroid Build Coastguard Worker#### Python example
369*1b3f573fSAndroid Build Coastguard Worker
370*1b3f573fSAndroid Build Coastguard WorkerNo presence:
371*1b3f573fSAndroid Build Coastguard Worker
372*1b3f573fSAndroid Build Coastguard Worker```python
373*1b3f573fSAndroid Build Coastguard Workerm = example.Msg()
374*1b3f573fSAndroid Build Coastguard Workerif m.foo != 0:
375*1b3f573fSAndroid Build Coastguard Worker  # "Clear" the field:
376*1b3f573fSAndroid Build Coastguard Worker  m.foo = 0
377*1b3f573fSAndroid Build Coastguard Workerelse:
378*1b3f573fSAndroid Build Coastguard Worker  # Default value: field may not have been present.
379*1b3f573fSAndroid Build Coastguard Worker  m.foo = 1
380*1b3f573fSAndroid Build Coastguard Worker```
381*1b3f573fSAndroid Build Coastguard Worker
382*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
383*1b3f573fSAndroid Build Coastguard Worker
384*1b3f573fSAndroid Build Coastguard Worker```python
385*1b3f573fSAndroid Build Coastguard Workerm = example.Msg()
386*1b3f573fSAndroid Build Coastguard Workerif m.HasField('foo'):
387*1b3f573fSAndroid Build Coastguard Worker  # Clear the field:
388*1b3f573fSAndroid Build Coastguard Worker  m.ClearField('foo')
389*1b3f573fSAndroid Build Coastguard Workerelse:
390*1b3f573fSAndroid Build Coastguard Worker  # Field is not present, so set it.
391*1b3f573fSAndroid Build Coastguard Worker  m.foo = 1
392*1b3f573fSAndroid Build Coastguard Worker```
393*1b3f573fSAndroid Build Coastguard Worker
394*1b3f573fSAndroid Build Coastguard Worker#### Ruby example
395*1b3f573fSAndroid Build Coastguard Worker
396*1b3f573fSAndroid Build Coastguard WorkerNo presence:
397*1b3f573fSAndroid Build Coastguard Worker
398*1b3f573fSAndroid Build Coastguard Worker```ruby
399*1b3f573fSAndroid Build Coastguard Workerm = Msg.new
400*1b3f573fSAndroid Build Coastguard Workerif m.foo != 0
401*1b3f573fSAndroid Build Coastguard Worker  # "Clear" the field:
402*1b3f573fSAndroid Build Coastguard Worker  m.foo = 0
403*1b3f573fSAndroid Build Coastguard Workerelse
404*1b3f573fSAndroid Build Coastguard Worker  # Default value: field may not have been present.
405*1b3f573fSAndroid Build Coastguard Worker  m.foo = 1
406*1b3f573fSAndroid Build Coastguard Workerend
407*1b3f573fSAndroid Build Coastguard Worker```
408*1b3f573fSAndroid Build Coastguard Worker
409*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
410*1b3f573fSAndroid Build Coastguard Worker
411*1b3f573fSAndroid Build Coastguard Worker```ruby
412*1b3f573fSAndroid Build Coastguard Workerm = Msg.new
413*1b3f573fSAndroid Build Coastguard Workerif m.has_foo?
414*1b3f573fSAndroid Build Coastguard Worker  # Clear the field:
415*1b3f573fSAndroid Build Coastguard Worker  m.clear_foo
416*1b3f573fSAndroid Build Coastguard Workerelse
417*1b3f573fSAndroid Build Coastguard Worker  # Field is not present, so set it.
418*1b3f573fSAndroid Build Coastguard Worker  m.foo = 1
419*1b3f573fSAndroid Build Coastguard Workerend
420*1b3f573fSAndroid Build Coastguard Worker```
421*1b3f573fSAndroid Build Coastguard Worker
422*1b3f573fSAndroid Build Coastguard Worker#### Javascript example
423*1b3f573fSAndroid Build Coastguard Worker
424*1b3f573fSAndroid Build Coastguard WorkerNo presence:
425*1b3f573fSAndroid Build Coastguard Worker
426*1b3f573fSAndroid Build Coastguard Worker```js
427*1b3f573fSAndroid Build Coastguard Workervar m = new Msg();
428*1b3f573fSAndroid Build Coastguard Workerif (m.getFoo() != 0) {
429*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
430*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(0);
431*1b3f573fSAndroid Build Coastguard Worker} else {
432*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
433*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(1);
434*1b3f573fSAndroid Build Coastguard Worker}
435*1b3f573fSAndroid Build Coastguard Worker```
436*1b3f573fSAndroid Build Coastguard Worker
437*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
438*1b3f573fSAndroid Build Coastguard Worker
439*1b3f573fSAndroid Build Coastguard Worker```js
440*1b3f573fSAndroid Build Coastguard Workervar m = new Msg();
441*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) {
442*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
443*1b3f573fSAndroid Build Coastguard Worker  m.clearFoo()
444*1b3f573fSAndroid Build Coastguard Worker} else {
445*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
446*1b3f573fSAndroid Build Coastguard Worker  m.setFoo(1);
447*1b3f573fSAndroid Build Coastguard Worker}
448*1b3f573fSAndroid Build Coastguard Worker```
449*1b3f573fSAndroid Build Coastguard Worker
450*1b3f573fSAndroid Build Coastguard Worker#### Objective C example
451*1b3f573fSAndroid Build Coastguard Worker
452*1b3f573fSAndroid Build Coastguard WorkerNo presence:
453*1b3f573fSAndroid Build Coastguard Worker
454*1b3f573fSAndroid Build Coastguard Worker```Objective-C
455*1b3f573fSAndroid Build Coastguard WorkerMsg *m = [[Msg alloc] init];
456*1b3f573fSAndroid Build Coastguard Workerif (m.foo != 0) {
457*1b3f573fSAndroid Build Coastguard Worker  // "Clear" the field:
458*1b3f573fSAndroid Build Coastguard Worker  m.foo = 0;
459*1b3f573fSAndroid Build Coastguard Worker} else {
460*1b3f573fSAndroid Build Coastguard Worker  // Default value: field may not have been present.
461*1b3f573fSAndroid Build Coastguard Worker  m.foo = 1;
462*1b3f573fSAndroid Build Coastguard Worker}
463*1b3f573fSAndroid Build Coastguard Worker```
464*1b3f573fSAndroid Build Coastguard Worker
465*1b3f573fSAndroid Build Coastguard WorkerExplicit presence:
466*1b3f573fSAndroid Build Coastguard Worker
467*1b3f573fSAndroid Build Coastguard Worker```Objective-C
468*1b3f573fSAndroid Build Coastguard WorkerMsg *m = [[Msg alloc] init];
469*1b3f573fSAndroid Build Coastguard Workerif (m.hasFoo()) {
470*1b3f573fSAndroid Build Coastguard Worker  // Clear the field:
471*1b3f573fSAndroid Build Coastguard Worker  [m clearFoo];
472*1b3f573fSAndroid Build Coastguard Worker} else {
473*1b3f573fSAndroid Build Coastguard Worker  // Field is not present, so set it.
474*1b3f573fSAndroid Build Coastguard Worker  [m setFoo:1];
475*1b3f573fSAndroid Build Coastguard Worker}
476*1b3f573fSAndroid Build Coastguard Worker```
477