【问题标题】:Protobuf defaults vs. "missing required fields" when serializing序列化时 Protobuf 默认值与“缺少必填字段”
【发布时间】:2015-04-09 16:55:55
【问题描述】:

包含具有默认值的必填字段的 ProtoBuf 消息上的 SerializeToString() 方法总是抛出 EncodeError ,说明该消息缺少那些必填字段。但是,如果我检查字段的值,则会设置所有默认值。例如:

// mymessage.proto
message MyMessage {
    required int32 val = 1 [default=18];
}

然后在python中:

from mymessage_pb2.py import MyMessage
m = MyMessage()
print m.val # Shows m.val == 18
print m.SerializeToString() # EncodeError

另一方面,如果我这样做:

m.val = m.val
print m.SerializeToString() # No Error

很明显,尽管在初始化时具有默认值,但它只需要触及每个字段。对我来说,使用默认值的要点之一是只要求某人更新非默认字段(或他们需要更改的字段),因此这种自行设置的方法是一个非常抱歉的解决方案。

将字段标记为 optional 不是解决方案,因为根据我们的规范,这些字段是合法需要的。

更新:我尝试的变通方法包括 MergeFrom 和 CopyFrom,但均未奏效。所以我写了这个:

def ActuallyInit(obj):
    err = []
    obj.IsInitialized(err)
    for field in err:
        attr = obj.__getattribute__(field)
        try:
            obj.__setattr__(field, attr)
        except:
            ActuallyInit(attr)

然后创建他们的 protobuf 对象并将其传递给ActuallyInit,后者递归地将每个字段设置为自身。这似乎是一个丑陋的 hack,所以我将下面的问题留待解决。

问题:有没有办法创建 ProtoBuf 消息实例并“说服”它每个已经初始化为默认的字段实际上都不是错误?

【问题讨论】:

    标签: python protocol-buffers


    【解决方案1】:

    这是按预期工作的。 required 表示“作者必须明确填写此字段,不要使用默认值”。如果您想要一个允许作者保留其默认值的字段,那么您需要optional。这实际上是requiredoptional 之间的唯一 区别,因此根本没有理由将required 与默认值一起使用。可以说,如果使用默认值定义了 required 字段,Protobuf 编译器应该会引发错误,但我当时并没有考虑实现该限制。

    (FWIW,required 长期以来一直被认为是a misfeature,并已在 Protobuf v3 中删除。)

    【讨论】:

    • 不知何故,我从文档中脱离出来,理解如果我将一个字段标记为可选,它不一定是消息流的一部分。我绝对没有得到这意味着最终用户必须简单地触摸该字段的印象。感谢您的链接。
    • @Thomas 好吧,这并不遥远:“触摸字段”使其成为消息流的一部分,否则实际上根本不会发送,在这种情况下,接收者使用默认值.
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多