Comment #38 on issue 57 by christophedehlinger: null values should be treated as no value
http://code.google.com/p/protobuf/issues/detail?id=57

Kenton,
I'm in the process of migrating from JSON to Protobuf, and I must say I was very surprised and disappointed when I came across this behaviour in the Java binding.

Surprised, because, as mentioned by others, nulls in Java are an idiomatic way to flag the absence of a value. I completely expected protobuf-java to treat them as
such. Many libraries I've come across have no clear methods, but instead use
set(null), or at least consider it equivalent to clear(). This is really standard stuff.

Disappointed, because of the boilerplate then required when your model objects have
many optional fields.

I don't know if you ever got an answer to your last comment, anyway here's an example.

If your model object is:

public interface Person {
  public String getFirstName();
  public String getLastName();
  public String getAddress1();
  public String getAddress2();
  ...
  public Integer getAge();
}

where some or most fields are optional, then instead of

Person p = ...;
ProtoPerson pp = ProtoPerson.Builder.newBuilder()
  .setFirstName(p.getFirstName())
  .setLastName(p.getLastName())
  .setAddress1(p.getAddress1())
  .setAddress2(p.getAddress1())
  ...
  .setAge(p.getAge())
  .build();

you have to write:

ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
if (p.getFirstName() != null) builder.setFirstName(p.getFirstName());
if (p.getLastName() != null) builder.setLastName(p.getLastName());
if (p.getAddress1() != null) builder.setAddress1(p.getAddress1());
if (p.getAddress2() != null) builder.setAddress2(p.getAddress2());
...
if (p.getAge() != null) builder.setAge(p.getAge());
ProtoPerson pp = p.build();

Not so great, twice the character count already... It gets worse if you need to mix in some value processing (such as escaping or capitalizing or filtering or formatting
or whatever) that you'd rather not perform twice for each field.

ProtoPerson pp = ProtoPerson.Builder.newBuilder()
  .setFirstName(doSomeModeratelyCostlyEscaping(p.getFirstName()))
  .setLastName(doSomeModeratelyCostlyEscaping(p.getLastName()))
  .setAddress1(doSomeModeratelyCostlyEscaping(p.getAddress1()))
  .setAddress2(doSomeModeratelyCostlyEscaping(p.getAddress1()))
  .build();

And you get:

ProtoPerson.Builder builder = ProtoPerson.Builder.newBuilder();
String eFirstName = doSomeModeratelyCostlyEscaping(p.getFirstName())
if (eFirstName != null) builder(p.getFirstName());
String eLastName = doSomeModeratelyCostlyEscaping(p.getLastName())
if (eLastName != null) builder(p.getLastName());
String eAddress1 = doSomeModeratelyCostlyEscaping(p.getAddress1())
if (eAddress1 != null) builder(p.getAddress1());
String eAddress2 = doSomeModeratelyCostlyEscaping(p.getAddress2())
if (eAddress2 != null) builder(p.getAddress2());
ProtoPerson pp = p.build();

which is barely legible.

My actual use case has many such classes with dozens of optional fields.

Granted, it's no big deal but, yuck.

IMHO, there should really be at least an option to have set(null)'s interpreted as
clears. I understand that there are no nulls in protobuf, but the point of
protobuf-java is not to implement the Protobuf model in Java. It is to provide an API to use Protobuf from Java, and thus it should be as friendly as possible to Java developers. And an important part of this is to embrace Java idioms when possible.

--
You received this message because you are listed in the owner
or CC fields of this issue, or because you starred this issue.
You may adjust your issue notification preferences at:
http://code.google.com/hosting/settings

--
You received this message because you are subscribed to the Google Groups "Protocol 
Buffers" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/protobuf?hl=en.

Reply via email to