我正在研究从数据库中获取数据并构造protobuff消息的东西。鉴于可以从数据库中为某些字段提取空值,我将在尝试构造protobuff消息时获得Null指针异常。在线程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构造期间是否还有其他可行的有效方法来处理空值?
答案 0 :(得分:42)
免责声明:每天使用protobufs从Google员工处回答。我决不以任何方式代表谷歌。
Person
而不是PersonProto
或ProtoPerson
命名。编译的protobufs只是您正在使用的语言指定的类定义,并有一些改进。添加“Proto”是额外的冗长。YourMessage.hasYourField()
代替YourMessage.getYourField() != null
。 protobuf字符串的默认值是一个空字符串, NOT 等于null。然而,无论您的字段是未设置或清除还是空字符串,.hasYourField()
始终返回false。见default values for common protobuf field types。null
。即使对于protobuf之外,null
{{ 3}}。请改用.clearYourField()
。Person.Builder
类 NOT 有.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
是您创建的人物对象,其属性值可以是空字符串,空格或空,那么我建议使用causes all sorts of problems:
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();
答案 1 :(得分:17)
wrappers.proto支持可为空的值:
示例
#client
import socket
HOST_IP = '127.0.0.1'
DEST_PORT = 1731
my_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
my_socket.connect((HOST_IP,DEST_PORT))
data1 = "test1"
print("client send")
my_socket.sendall(data1.encode())
my_socket.sendall("second send ".encode())
my_socket.close()
答案 2 :(得分:9)
对此没有简单的解决方案。我建议只处理空检查。但如果你真的想摆脱它们,这里有几个想法:
setOrClearFoo()
个方法。 Java代码生成器为此提供insertion points(参见该页末尾)。get*()
的{{1}}方法,调用每个方法,检查p
,然后调用null
方法set*()
1}}如果非null。这将具有额外的优势,即每次添加新字段时都不必更新复制代码,但它比编写明确复制每个字段的代码要慢得多。