处理protobuffers中的空值

我正在研究从数据库中获取数据并构造protobuff消息的东西。 鉴于可以从数据库中为某些字段提取空值,我将在尝试构建protobuff消息时获得Null指针exception。 从线程http://code.google.com/p/protobuf/issues/detail?id=57中的protobuffs中不支持知道null,我想知道处理NPE的唯一其他方法是抛出是将手动检查插入到与原型相对应的java文件中,如下所示!

message ProtoPerson{ optional string firstName = 1; optional string lastName = 2; optional string address1 = 3; } 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()); ... 

那么有人可以澄清是否有任何其他可能有效的方法来处理protobuff构造期间的空值?

对此没有简单的解决方案。 我建议只处理空检查。 但如果你真的想摆脱它们,这里有几个想法:

  • 您可以编写一个代码生成器插件 ,它将setOrClearFoo()方法添加到每个Java类。 Java代码生成器为此提供插入点 (请参阅该页面的末尾)。
  • 您可以使用Javareflection迭代pget*()方法,调用每个方法,检查null ,然后调用builderset*()方法(如果为非null)。 这将具有额外的优势,即每次添加新字段时都不必更新复制代码,但它比编写明确复制每个字段的代码要慢得多。

免责声明:每天使用protobufs从Google员工处回答。 我绝不以任何方式代表谷歌。

  1. 将您的proto Person命名为PersonProtoProtoPerson 。 编译的protobufs只是您正在使用的语言指定的类定义,并有一些改进。 添加“Proto”是额外的冗长。
  2. 使用YourMessage.hasYourField()而不是YourMessage.getYourField() != null 。 protobuf字符串的默认值是一个空字符串,它不等于null。 然而,无论您的字段是未设置或清除还是空字符串, .hasYourField()始终返回false。 请参阅常用protobuf字段类型的默认值 。
  3. 您可能已经知道了,但我想明确地说: 不要以编程方式将protobuf字段设置为null 即使对于protobuf之外, null也会导致各种问题 。 请改用.clearYourField()
  4. Person.Builder类没有.newBuilder()方法。 Person做。 像这样理解Builder模式 :只有在没有它的情况下才创建新构建器。

重写你的protobuf:

 message Person { optional firstName = 1; optional lastName = 2; optional address1 = 3; } 

重写你的逻辑:

 Person thatPerson = Person.newBuilder() .setFirstName("Aaa") .setLastName("Bbb") .setAddress1("Ccc") .build(); Person.Builder thisPersonBuilder = Person.newBuilder() if (thatPerson.hasFirstName()) { thisPersonBuilder.setFirstName(thatPerson.getFirstName()); } if (thatPerson.hasLastName()) { thisPersonBuilder.setLastName(thatPerson.getLastName()); } if (thatPerson.hasAddress1()) { thisPersonBuilder.setAddress1(thatPerson.getAddress1()); } Person thisPerson = thisPersonBuilder.build(); 

如果thatPerson是你创建的人物对象,其属性值可以是空字符串,空格或null,那么我建议使用Guava的Strings库 :

 import static com.google.common.base.Strings.nullToEmpty; Person.Builder thisPersonBuilder = Person.newBuilder() if (!nullToEmpty(thatPerson.getFirstName()).trim().isEmpty()) { thisPersonBuilder.setFirstName(thatPerson.getFirstName()); } if (!nullToEmpty(thatPerson.hasLastName()).trim().isEmpty()) { thisPersonBuilder.setLastName(thatPerson.getLastName()); } if (!nullToEmpty(thatPerson.hasAddress1()).trim().isEmpty()) { thisPersonBuilder.setAddress1(thatPerson.getAddress1()); } Person thisPerson = thisPersonBuilder.build();