Protocol Buffers has had required
and ʻoptional` removed in proto3.
Regarding the process of deletion in the first place, see @qsona's Entry for an easy-to-understand summary. Thank you.
The problem is that in proto3, each field has a default value, so the field with the default value is from the user side.
A value similar to the intentionally set default value
Default value not set because it does not exist
It means that you cannot judge either.In other words, how to express an optional value.
There are several options, but the answer from Stack Overflow is helpful. Will be.
schema.proto
message User {
int32 id = 1;
bool has_name = 2; //Indicates the existence of name
string name = 3; //Actual value
}
Example(Java)
User user1 = User.newBuilder()
.setHasName(true)
.setName("Tom")
.build();
User user2 = User.newBuilder()
.setHasName(false) //The default value is false, so you don't actually need a set
.build();
user1.getHasName(); // true
user1.getName(); // "Tom"
user2.getHasName(); // false
user2.getName(); // ""
schema.proto
message User {
int32 id = 1;
oneof name_optional {
string name = 2; //Wrap the handling value with one of
}
}
Example(Java)
User user1 = User.newBuilder()
.setName("Tom")
.build();
User user2 = User.newBuilder()
.build();
user1.getNameOptionalCase(); // User.NameOptionalCase.NAME
user1.getName(); // "Tom"
user2.getNameOptionalCase(); // User.NameOptionalCase.NAMEOPTIONAL_NOT_SET
user2.getName(); // ""
google / protobuf / wrappers.proto
schema.proto
message User {
int32 id = 1;
google.protobuf.StringValue name = 2;
}
Example(Java)
User user1 = User.newBuilder()
.setName(StringValue.newBuilder().setValue("Tom").build())
.build();
User user2 = User.newBuilder()
.build();
user1.hasName(); // true
user1.getName().getValue(); // "Tom"
user2.hasName(); // false
user2.getName().getValue(); // ""
The first thing we all have in common is that no matter which option you choose, you cannot force it to be an optional value. * 1
Therefore, for any option, it is necessary to procedurally perform check for existence
→ process for value
.
In 1, the notation is very simple, but the compiler cannot guarantee the relationship between the two fields, and it is necessary to support it with comments.
Compared to 1, 2 has the advantage of being able to express the presence or absence of fields at the compiler level, but it is a little strange usage from one of where multiple fields are assumed.
3 is intuitive and easy to use when dealing with optional values, but it also has some disadvantages.
--Slightly verbose, such as needing a builder for wrappers or calling getValue ()
to retrieve values
--If you want to make a non-primitive value optional, you need to use it together with 1 or 2, and there are two ways to express optional, which cannot be unified.
Example:
schema.proto
message User {
int32 id = 1;
Fullname fullname = 2;
}
message Fullname {
string first_name = 1;
string last_name = 2;
}
For example, in such a case, wrapper is only provided with the following types, so it cannot be used if you want to make each full name optional.
DoubleValue
FloatValue
Int64Value
UInt64Value
Int32Value
UInt32Value
BoolValue
StringValue
BytesValue
Therefore, if you want to unify optional expressions, it is easy to understand to unify with 1 or 2.
Protocol Buffers is a schema language with compact specifications, and features low learning costs and good readability. However, for that reason, some expressions that are common to others have been removed, and I think that more expressions can be made by using them while covering them in a timely manner.
Recommended Posts