处理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迭代
p
的get*()
方法,调用每个方法,检查null
,然后调用builder
的set*()
方法(如果为非null)。 这将具有额外的优势,即每次添加新字段时都不必更新复制代码,但它比编写明确复制每个字段的代码要慢得多。
免责声明:每天使用protobufs从Google员工处回答。 我绝不以任何方式代表谷歌。
- 将您的proto
Person
命名为PersonProto
或ProtoPerson
。 编译的protobufs只是您正在使用的语言指定的类定义,并有一些改进。 添加“Proto”是额外的冗长。 - 使用
YourMessage.hasYourField()
而不是YourMessage.getYourField() != null
。 protobuf字符串的默认值是一个空字符串,它不等于null。 然而,无论您的字段是未设置或清除还是空字符串,.hasYourField()
始终返回false。 请参阅常用protobuf字段类型的默认值 。 - 您可能已经知道了,但我想明确地说: 不要以编程方式将protobuf字段设置为
null
。 即使对于protobuf之外,null
也会导致各种问题 。 请改用.clearYourField()
。 -
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();