【问题标题】:How to deal with unknown protobuf fields in Java?如何处理 Java 中未知的 protobuf 字段?
【发布时间】:2019-09-29 03:30:30
【问题描述】:

我有一个 Java 应用程序,它从另一台计算机读取一些 protobuf 数据,然后可以修改一些值并将其写回。用户很可能可以使用过时的 .proto 文件读取数据,因此在这种情况下会有一些它不理解的字段。在写回所做的更改时,我最终希望保留未知数据;但是,我可以只检测到有未知数据(提示用户升级他/她的应用程序)。我不清楚如何处理 Java 中的未知字段。

如果有帮助,我正在使用版本 2 .proto 文件,因为我需要它与远程计算机上的 nanopb 兼容。

这个question 让我参与其中,但我的问题与 JSON 无关。

【问题讨论】:

  • 您是否测试过用户使用过时的 .proto 文件打开数据时的行为?在这种情况下,您是否可以捕获并响应一个简单的异常?
  • 如果您使用 protoc 生成 java 类,它包含 unknownFields 字段,它将填充标签编号和值(因为新的 proto 包含例如标签 4,在过时的 proto 文件中不可用)

标签: java protocol-buffers protobuf-java


【解决方案1】:

首先请注意当您说未知领域时。在 protobuf 中,您可以根据定义拥有未知字段,但另一方面 - 我想这是您的情况 - 您可以拥有当前 proto 文件中没有的字段。

在这两种情况下,您都可以轻松访问这些值。假设您有一个名为 foo 的原始消息。

您必须访问描述符并按名称从那里获取字段,最后获取如下示例的值:

Builder builder = foo.toBuilder();
FieldDescriptor field = builder.getDescriptorForType().findFieldByName("whatever field");
Object obj = builder.getField(field);

// if your field is int32 cast to int
int value = (int) obj

如果您希望写入“未知”值,您可以反过来:

Builder builder = foo.toBuilder();
FieldDescriptor field = builder.getDescriptorForType().findFieldByName("whatever field");
builder.setField(field, 100); // 100 is an example int value
Foo foo = builder.build();

如果您真的想插入原始定义的未知字段,您必须执行以下操作:

 UnknownFieldSet.Field seqField = UnknownFieldSet.Field
            .newBuilder()
            .addFixed32(100) // 100 is an example int value
            .build();

 UnknownFieldSet unkFieldSet = UnknownFieldSet
            .newBuilder()
            .addField(99, seqField) // 99 is a proto index number chosen by me
            .build();

 Foo message = foo.toBuilder().setUnknownFields(unkFieldSet).build();

再次读取已定义的未知字段由以下人员完成:

 foo.toBuilder().getUnknownFields()....

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2013-06-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-01
    • 1970-01-01
    • 2021-12-11
    • 2018-06-23
    • 1970-01-01
    相关资源
    最近更新 更多