Since protobuf release 3.15, proto3 supports using the optional keyword (just as in proto2) to give a scalar field presence information.
syntax = "proto3";
message Foo {
int32 bar = 1;
optional int32 baz = 2;
}
A has_baz()/hasBaz() method is generated for the optional field above, just as it was in proto2.
Under the hood, protoc effectively treats an optional field as if it were declared using a oneof wrapper, as CyberSnoopy’s answer suggested:
message Foo {
int32 bar = 1;
oneof optional_baz {
int32 baz = 2;
}
}
If you’ve already used that approach, you can now simplify your message declarations (switch from oneof to optional) and code, since the wire format is the same.
The nitty-gritty details about field presence and optional in proto3 can be found in the Application note: Field presence doc.
Historical note: Experimental support for optional in proto3 was first announced on Apr 23, 2020 in this comment. Using it required passing protoc the --experimental_allow_proto3_optional flag in releases 3.12-3.14.