4

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?

vatsal mevada
  • 5,148
  • 7
  • 39
  • 68
  • 2
    Why don't you like the first approach? For best practices you can check out: https://developers.google.com/protocol-buffers/docs/proto3#enum or https://developers.google.com/protocol-buffers/docs/reference/java-generated#enum – San P Mar 07 '21 at 23:39
  • @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`. – vatsal mevada Mar 08 '21 at 04:32

2 Answers2

0

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

Cash Lo
  • 1,052
  • 1
  • 8
  • 20
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;
}
Miri
  • 105
  • 1
  • 3