Google协议缓冲区检查是否已设置字段

时间:2016-11-23 19:13:28

标签: java protocol-buffers

我正在迭代GPB消息的字段,并且必须找出消息中已设置的字段列表

public void printFields(Person person){
Builder builder = person.toBuilder();
Descriptor descriptor = Person.getDescriptor();
List<FieldDescriptor> fields = descriptor.getFields();
for(FieldDescriptor fd : fields){
Object value = builder.get(fd); //this gives the value
// how to check if this field is set or not
}
}

value检查为null并没有帮助,因为消息中也可以有原始类型。 我已经阅读了有关消息类的hasXXX()方法,它告诉XXX是否具有默认值或显式值,但是如何使用builder / descriptor / fieldDescriptor调用它们。

3 个答案:

答案 0 :(得分:0)

已经晚了,但对其他人可能有用..

以下代码将打印修改后的属性名称及其值。你可以改变它来识别proto中的填充属性

    Map<Descriptors.FieldDescriptor, Object> modifiedFields = proto.getAllFields();

    for(Descriptors.FieldDescriptor fieldDescriptor : modifiedFields.keySet())
    {
        int protNum = fieldDescriptor.toProto().getNumber();
        Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
        Object value = modifiedFields.get(fieldDescriptor);

        System.out.println(fieldDescriptor.getFullName());
        System.out.println(value);
    }

答案 1 :(得分:0)

如果您使用的是Java 8,则可以使用流式API查找已定义的字段:

List<Descriptors.FieldDescriptor> definedPersonFields = Person.getDescriptor()
      .getFields()
      .stream()
      .filter(Person::hasField)
      .collect(Collectors.toList())

答案 2 :(得分:-1)

为什么需要使用descriptor / fieldDescriptor?如果您定义“option optimize_for = LITE_RUNTIME”,它们甚至不可用。 无论如何,你可以在Person.Builder或者只有Person上做到这一点,例如:

   Builder builder = person.toBuilder();
   if (builder.hasXXX()){
          XXX xxx = builder.getXXX();
   }