Protobuf默认值与序列化时的“缺少必需字段”

2024-09-27 07:24:36 发布

您现在位置:Python中文网/ 问答频道 /正文

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

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

然后在python中:

^{pr2}$

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

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

很明显,它只需要触摸每个字段,尽管初始化时有一个默认值。对我来说,拥有默认值的一个主要点是只需要有人更新非默认字段(或那些需要更改的字段),所以这个setittoself方法是一个非常糟糕的解决方案。在

将字段标记为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,后者递归地将每个字段设置为自己。这似乎是一个丑陋的黑客攻击,所以我留下下面的问题。在

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


Tags: 方法obj消息fieldmessageval解决方案proto
1条回答
网友
1楼 · 发布于 2024-09-27 07:24:36

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

(FWIW,required长期以来被认为是{a1},并在protobufv3中被删除了。)

相关问题 更多 >

    热门问题