【问题标题】:protobuf required field and default valueprotobuf 必填字段和默认值
【发布时间】:2013-03-12 11:16:47
【问题描述】:

我是 protobuf 的新手,我已经开始考虑以下简单的示例

message Entry {
  required int32 id = 1;
}

由 c++ 代码使用

#include <iostream>
#include "example.pb.h"
int main() {
  std::string mySerialized;
  {
    Entry myEntry;
    std::cout << "Serialization succesfull " 
              << myEntry.SerializeToString(&mySerialized) << std::endl;
    std::cout << mySerialized.size() << std::endl;
  }
  Entry myEntry;
  std::cout << "Deserialization successfull "
            << myEntry.ParseFromString(mySerialized) << std::endl;
}

即使“id”字段是必需的,由于没有设置,所以序列化缓冲区的大小为0(??)。

当我反序列化消息时发生错误:

[libprotobuf ERROR google/protobuf/message_lite.cc:123] Can't parse message of type "Entry" because it is missing required fields: id

这是正常行为吗?

弗朗西斯科

ps- 如果我用值 0 初始化“id”,则行为不同

pps-SerializeToString 函数返回 true,ParseFromString 返回 false

【问题讨论】:

  • 这些方法没有返回值来告诉你它是否有效吗?你在检查吗?
  • 请注意,零长度缓冲区在 protobuf 中完全有效 - 如果没有要序列化的字段,这就是您得到的结果

标签: c++ protocol-buffers


【解决方案1】:

我不认为我完全理解你的问题,但无论如何我都会尝试回答。希望这对您有所帮助:)

是的,这是正常行为。仅当字段对消息很重要时,才应添加 required。这在语义上是有意义的。 (为什么要跳过必填字段)。为了强制执行此操作,protobuf 不会解析消息。

看到标有数字1的字段是必填项,has_id()方法返回false。所以它根本不会解析消息。

developer guide 中建议不要使用必填字段。

必填项是永远的 您应该非常小心地将字段标记为必填项。如果在某些时候您希望停止写入或发送必填字段,则将该字段更改为可选字段会出现问题——老读者会认为没有此字段的消息不完整,可能会无意中拒绝或丢弃它们。您应该考虑为您的缓冲区编写特定于应用程序的自定义验证例程。 Google 的一些工程师得出的结论是,使用 required 弊大于利。他们更喜欢只使用可选的和重复的。但是,这种观点并不普遍。

还有

您添加的任何新字段都应该是可选的或重复的。这意味着使用“旧”消息格式的代码序列化的任何消息都可以由新生成的代码解析,因为它们不会丢失任何必需的元素。您应该为这些元素设置合理的默认值,以便新代码可以与旧代码生成的消息正确交互。类似地,新代码创建的消息可以由旧代码解析:旧二进制文件在解析时会忽略新字段。但是,未知字段不会被丢弃,如果消息稍后被序列化,未知字段也会随之序列化——因此,如果将消息传递给新代码,新字段仍然可用。请注意,Python 目前无法保存未知字段

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-02-13
    • 2012-09-09
    • 1970-01-01
    相关资源
    最近更新 更多