Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

hasX is an important feature, dropped from proto3 #159

Closed
justinsb opened this issue Jan 10, 2015 · 2 comments
Closed

hasX is an important feature, dropped from proto3 #159

justinsb opened this issue Jan 10, 2015 · 2 comments

Comments

@justinsb
Copy link

I have always been impressed with protocol buffers - there are so many nuances to the design that I appreciate as I keep using it. One that I have found especially useful is that hasX is supported on every field; even primitives. For example, I have previously written JSON <-> protobuf mappings, and this allowed me to differentiate between the "x=0" and the "x not present" case. This also maps well to databases, where x=0 and x=NULL are also different. Many/most real world systems have 0 != null, so it seems odd for protobuf to switch sides on this argument.

So can we keep hasX working as it was in proto2?

If nothing else, this is a huge behavioural change that will impede migration to proto3 (after setX(0); hasX() then returns true in proto2, false in proto3). Because it is value-dependent it will be impractical to migrate code that calls hasX() safely - e.g. static analysis will be impossible.

If that is off the table, can we at least have an option to keep the 0 != null behaviour, with the new proto3 syntax?

@droyop
Copy link

droyop commented Jan 22, 2015

Well there are a couple of workarounds for this if I understood well the changelog (It applies only to primitives) I did this on the fly so forgive me if there's something wrong. Both approaches are annoying anyway.

a) you can specify a null indicator like in the good ol' days.

bool secondNameIndicator = 1
String secondName = 2

Then you can set it...

setSecondName("John"); AND setSecondNameIndicator(true);

... check it ...

if (getSecondNameIndicator())

... get it ...

getSecondName();

b) This applies only to primitives so there's really nothing stopping you from doing

message Person {
optional string name = 1;

message SecondName {
optional string value = 1;
}
optional SecondName value = 2;
}

and then you can set it...

person.setSecondName(Person.SecondName.newBuilder().setValue("Jr"));

...check it (This works with non-primitives normally)...

if (person.hasSecondName())

... get it ...

person.getSecondName().getValue()

@liujisi
Copy link
Contributor

liujisi commented Feb 26, 2015

If you need the field presence info for primitive fields, there will be "well known types" protos introduced in 3.0 beta releases, which includes built-in wrapper types. e.g.

message IntegerValue {
  optional int32 value = 1;
} 

then you can write

message MyMessage {
  optional int32 field1 = 1;
  optional IntegerValue field2 = 2;
}

This is aligned with native languages (like Java). You can have

class MyMessage {
  public int field1;
  public Integer field2;
}

There's no field presence info for field1, but there is for field2, where you can set it to null.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants