【问题标题】:Protobuf parser parses other objects?Protobuf 解析器解析其他对象?
【发布时间】:2018-04-01 21:01:32
【问题描述】:

我一直在为我的 Java 项目使用协议缓冲区。我发现 protobuf 对象的解析器解析其他 Protobuf 数据并且不会引发异常。相反,它返回解析器类型的对象,没有任何数据(不是默认实例)

下面是我的测试原型文件

option java_package = "tester";
option java_outer_classname = "TestProto";

message A{
    string message = 1;
}

message B{
    int64 id = 1;
}

下面是我的测试代码

 TestProto.A a = TestProto.A.newBuilder().setMessage("My Test Message").build();
 TestProto.B b = TestProto.B.getDefaultInstance().getParserForType().parseFrom(a.toByteString());

 System.out.println("Is default instnace :" + (b.getDefaultInstanceForType() == b));

此代码正常运行,结果为“假”。

我无法理解这种行为,我需要一种情况,我必须解析一些序列化的 protobuf 对象,如果一个解析器失败,我必须尝试另一个解析器。我该如何解决这个问题。

谢谢。

【问题讨论】:

  • 检查getUnknownFields(或getUnknownFieldSet,或类似的内容。我忘记了确切的方法名称)。
  • 但是,一般来说,b.getDefaultInstanceForType() == b 是错误的:使用equals 来比较实例。
  • 你通常会很难做到这一点,因为在 proto3 中字段默认为optional。这意味着如果两条消息具有完全不同的字段(和字段 ID),它们仍然可以相互分配。只有内容会丢失,因为解析器假定它只是一个它不知道的可选字段。
  • 但是在这个具体的例子中应该有一个错误,因为相同的字段 ID (1) 用于两种不同的类型。
  • @Matthias247 它可以通过“打包”逻辑进行解析,该逻辑将匹配长度前缀;不引起 varint 违规需要很大的运气,但理论上是可能的;我会认为除非它被“重复”它不会那样做,但是......嗯

标签: java protocol-buffers protobuf-java


【解决方案1】:

Protobuf 的前提是两端都事先知道 - 并同意 - 数据结构。如果您尝试用完全不同的结构解释消息,则保证为零。

  • 可能会引发错误
  • 它可以工作并为您呈现善意的胡言乱语
  • 它可以工作并将所需的所有内容保存为未知字段

一切皆有可能。

基本上:你不能依赖这种行为。

注意:对于某些更改,例如添加或删除字段(确保它们以后不会以不同的类型/含义重复使用),保证。这很好,也是意料之中的。但其他更改根本没有定义。


我需要一种情况,我必须解析一些序列化的 protobuf 对象,如果一个解析器失败,我必须尝试另一个解析器。我该如何解决这个问题。

你不能。

【讨论】:

  • 自我注意:我有 99.5% 的把握 protobuf-net 在这种情况下实际上会抛出异常。由于这是一个未定义的场景,这两种行为都不是更正确或更错误,但现在我想知道我是否应该至少让它表现得一样。但实际上:如果你遇到了这个问题,你已经把你的数据弄得一团糟,所以……也许最好不要管它。当然,这似乎不值得花太多时间。可能存在“我将打包的重复字段(其中曾经有一个值)更改为可选字段,但现在它失败了”的情况
  • “你不能。”可能并不总是正确的。如果您能够修改传入数据的架构,您可以使用oneof 关键字或Any 类型以及Any 字段实际持有的类型的某种描述来设计它。
  • @plastique 更改为 Any 是一个布局破坏性更改; oneof 不适用于问题所示的情况;所以是的,可以有种方法来处理这个在特定情况下,但是:不是显示的那个
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-14
  • 1970-01-01
相关资源
最近更新 更多