Protobuf的MessageToJson函数会移除值为0的字段。

11

我正在编写一个Python脚本,用于接收protobufs,将其转换为json对象,并将它们推送到另一个服务。我使用 json.loads(MessageToJson(protobuf)) 将protobuf转换为Python字典对象。稍后我使用 json.dumps(dictionary) 将其转换回json。

我的proto中有一个可选的枚举字段,例如:

enum C_TYPE
{
    AB = 0;
    BC = 1;
    CD = 2;
}

当我收到一个指定为BC的字段的proto时,一切都按照我的预期工作。但是,当我收到一个指定为AB的proto时,该字段被忽略了--它不会出现在Python字典或随后的JSON转换中。我发现的解决方法是使用json.loads(MessageToJson(protobuf, including_default_value_fields=True)),但这将为所有缺失的字段创建默认值,而不仅仅是具有0枚举的字段。它意味着枚举为0的字段已经不存在-但实际上并不是!

当枚举字段设置为0时,检索其值的正确方法是什么?

3个回答

15

没有正确的方式,我定义我的protobufs不正确。对于枚举字段,第一个值就是默认值。这意味着如果一个protobuf没有设置值,它就被设置为默认值,并且在转换为json时被忽略(除非你想保留所有默认值)。

因此,建议使用丢弃的名称作为默认值,以便能够正确区分何时已经设置了默认值。即我应该将我的protobuf定义为:

enum C_TYPE
{
    NONE = 0;
    AB = 1;
    BC = 2;
    CD = 3;
}

来自Protobuf关于可选字段和默认值的文档:

对于枚举类型,其默认值为枚举类型定义中列出的第一个值。这意味着,在枚举值列表的开头添加值时必须小心。

此外,来自golang/protobuf上的问题:

这是按照预期工作的。 proto3零值在JSON格式中也被省略了。零值应该是一个“可放弃”的值:如果序列化消息的发送方将字段设置为无效或不被识别的值,那么您也会看到它。


3
在C++的protobuf中,可以添加一个选项来始终打印基本字段。 将此选项添加到MessageToJson转换中,使得即使这些参数被设置为零,protobuf也会添加这些参数。
google::protobuf::util::JsonPrintOptions options;
options.always_print_primitive_fields = true;

0
在Python中,您可以将including_default_value_fields参数设置为True,以获取所有字段的值。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接