How to handle a nullable enum type field in a protobuf3 message?
Asked Answered
W

3

9

The following are my protobuf definitions:

enum Foo {
   BAR = 0;
   BAZ = 1;      
}

message UpdateRequest {
  string id = 1;
  Foo foo = 2;
  .
  .
  .
}

I need the foo field of the UpdateRequest to be nullable. However, if I don't set the value of this field then as per protobuf semantics it always ends up picking BAR as the default value.

Looking around, I found a couple of ways to handle this.

  1. Add an additional UNKNOWN value in the enum and map it to 0 so that this value will be used as the default value instead of BAR and I can treat this value as null.
enum Foo {
   UNKNOWN = 0;
   BAR = 1;
   BAZ = 2;      
}
  1. Use oneof construct.

However, somehow I feel that both of the above approaches are a kind of a workaround and I am not able to locate official documentation explaining the best practice to handle this case.

What is the best practice to handle this use case?

Woolf answered 6/3, 2021 at 16:12 Comment(2)
Why don't you like the first approach? For best practices you can check out: developers.google.com/protocol-buffers/docs/proto3#enum or developers.google.com/protocol-buffers/docs/reference/…Leboeuf
@SanP Thanks for those references to best practices. I ended up using the first approach only. I also noticed that there is experimental support for optional attributes, which appeared cleaner to me but unfortunately I won't be able to use that experimental feature in our production code. About the first approach one annoying thing was the scoping semantics of the enums. i.e. I have to keep in unique in the entire proto file which means I will have to use UNKNOWN_FOO instead of UNKNOWN.Woolf
A
0

You should be able to check the field using hasFoo(), while getFoo() will return BAR, hasFoo() should return false.

Allotropy answered 7/2, 2022 at 8:26 Comment(1)
Protoc doesn't compile the has methods for enumsMata
P
0

Continue reading only if you do not wish to use UNKNOWN enum value.

Do not know if the best practice but whenever I'm sending the object itself where the value can't be null, I use the enum value. And in requests (like your UpdateRequest) when it can be empty I'm using a string type instead and handle the conversion manually.

message Object {
  EnumProperty property = 1;

  enum EnumProperty {
    FIRST = 0;
    SECOND = 1;
    THIRD = 2;
  }
}

message ObjectUpdateRequest {
  string property = 1;
}
Pterodactyl answered 5/1, 2023 at 10:48 Comment(0)
G
0

In Protobuf 3, if the field is null then Protobuf will return Foo.UNRECOGNIZED. So you should be able to check whether the field is UNRECOGNIZED to determine if the field is set or not (which is a workaround for not having a hasFoo() function.

Good answered 30/5 at 22:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.