当前位置: 首页 > 知识库问答 >
问题:

将protobuff可选字段更改为

莫繁
2023-03-14

我有以下信息:

message Message {
    int64 id = 1;
    google.protobuf.FloatValue weight = 2;
    google.protobuf.FloatValue override_weight = 3;
}

我希望将权重和override_weight(可选字段)的类型更改为google.protobuf.DoubleValue,因此我所做的是流动:

message Message {
    int64 id = 1;
    oneof weight_oneof {
        google.protobuf.FloatValue weight = 2 [deprecated=true];
        google.protobuf.DoubleValue double_weight = 4;
    }
    oneof override_weight_oneof {
        google.protobuf.FloatValue override_weight = 3 [deprecated=true];
        google.protobuf.DoubleValue double_override_weight = 5;
    }
}

我的问题是,假设我有以前的protobuff消息编译器为旧消息编译的旧消息,我能将它们解析为新消息吗?文件对此非常模糊:

“将可选字段移入或移出其中一个:消息序列化和分析后,您可能会丢失一些信息(某些字段将被清除)。但是,您可以安全地将单个字段移入新字段中,并且如果已知只设置了一个字段,则可以移动多个字段。”

以前有人这样做过吗?这种情况的最佳做法是什么?

共有1个答案

向杜吟
2023-03-14

据我所知,其中一个字段只是使用它们的标签号进行序列化。序列化数据不指示字段是否是其中一个字段的一部分。这一切都由序列化程序和反序列化程序处理。因此,只要标记号不冲突,就可以假设它将在两个方向上工作,旧消息将发送给新的序列化程序,新消息将发送给旧的序列化程序。

您可以使用在线protobuf反序列化程序来测试这一点。

验证:代码确实产生相同的字节字符串。下面是我使用的消息定义和python代码。python代码将输出一个字节字符串,您可以复制并在Marc Gravell的解码器中使用。

syntax = "proto3";

message MessageA {
    int64 id = 1;
    float weight = 2;
    float override_weight = 3;
}

message MessageB {
    int64 id = 1;
    oneof weight_oneof {
        float weight = 2 [deprecated=true];
        double double_weight = 4;
    }
    oneof override_weight_oneof {
        float override_weight = 3 [deprecated=true];
        double double_override_weight = 5;
    }
}
import Example_pb2

# Set some data in the original message
msgA = Example_pb2.MessageA()
msgA.id = 1234
msgA.weight = 3.21
msgA.override_weight = 5.43

# Output the serialized bytes in a pretty format
str = 'msgA   = '
for x in msgA.SerializeToString():
    str += "{:02x} ".format(x)
print(str)

# Next set the original fields in the new message
msgB = Example_pb2.MessageB()
msgB.id = 1234
msgB.weight = 3.21
msgB.override_weight = 5.43

# Output the serialized bytes in a pretty format
str = 'msgB 1 = '
for x in msgB.SerializeToString():
    str += "{:02x} ".format(x)
print(str)

# And finally set the new fields in msgB
msgB.double_weight = 3.21
msgB.double_override_weight = 5.43

# Output the serialized bytes in a pretty format
str = 'msgB 2 = '
for x in msgB.SerializeToString():
    str += "{:02x} ".format(x)
print(str)

python脚本的输出是:

msgA   = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 1 = 08 d2 09 15 a4 70 4d 40 1d 8f c2 ad 40
msgB 2 = 08 d2 09 21 ae 47 e1 7a 14 ae 09 40 29 b8 1e 85 eb 51 b8 15 40

如您所见,设置原始字段时,消息A和消息B产生相同的字节字符串。只有在设置新字段时,才会得到不同的字符串。

 类似资料:
  • 问题内容: 是否可以将现有字段的属性从修改为? 如果没有,我该怎么办才能将我所有的文件保存起来? 我无法删除映射(因为所有文档都将消失),并且需要该旧字段进行分析。 问题答案: 不能修改现有字段,但是,您可以创建其他字段或子字段添加到您的领域。 我要使用后一种解决方案。因此,首先,将一个新的子字段添加到您现有的字段中,如下所示: 上面,我们已经添加了子场称为(被分析)现有的(这是) 接下来,我们需

  • 问题内容: 我有一个传统的postgres db,它具有将日期列强制转换为字段(不要问)。我想更改表和列以包含实际日期。因为这有效: 我天真地认为这可能有效: 但事实并非如此。有无知的线索吗? 问题答案: 这 恰好 符合OP的要求。我们这里有一个简单的思想/错别字。 在手册中了解有关ALTER TABLE的更多信息 。 演示: 提示:您写的不是。

  • 问题内容: 我有一个这样的类结构: 我的目标是调用get方法,然后检查它是否存在。如果存在,则返回该属性;如果不存在,则仅返回null。所以像这样: 当然,这不是正确的Java 8可选语法,但这就是我的“伪代码”。用Java 1行有什么办法实现这一点? 问题答案: 您正在描述的是方法: 如果值不存在,则可让您使用函数在内转换该值,如果不存在该值,则返回一个空值(可选)。 还要注意,您可以从映射函数

  • 我有以下请求json 我试图验证这个json,我的要求是,如果ParameterB存在,那么里面肯定会有一个列表shd存在,否则ParameterB是可选的。例如,如果ParameterB本身只是不存在,那么shd不是一个问题。 我正在寻找相同的java验证注释。我在key和value上使用了@NotNull,但不能决定在ParameterB上使用什么,因为它是list所在的数组 我在Parame

  • 我的avdl是这样定义的, 但是在事件发布和模式注册之后,我想让<code>street</code>类型也允许<code>null</code>值。我希望更改前后兼容。我该怎么做?在record完成之前定义一个新的名称空间会吗?(https://github.com/ga4gh/ga4gh-schemas/issues/344#unions或https://docs.oracle.com/dat

  • 我想创建一个作为源变量:。 我想创建一个可观察的,每次值更改时都会生成提要。 我是说,当我这样做的时候: 在我的代码的某个地方,我希望收到订阅的提要,等等。。。 有什么想法吗?