如何在Protobu中序列化嵌套消息中的默认值

2024-06-28 19:18:53 发布

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

正如标题所述,我有一个原型信息,里面有另一条信息,如下所示:

syntax = "proto3";

message Message
{
    message SubMessage {
        int32 number = 1;
    }

    SubMessage subMessage = 1;
}

我的example.json为空(这意味着到处都有默认值):

^{pr2}$

在我的python脚本中,我阅读以下消息:

with open("example.json", "r") as FH:
    exampleJSON = FH.read()

example_message = example.Message()
google.protobuf.json_format.Parse(exampleJSON, example_message)

当我检查example_message.subMessage.number的值时,0是正确的。在

现在我想把它转换成dict,其中所有的值都存在,甚至是默认值。 对于转换,我使用google.protobuf.json_format.MessageToDict()方法。 但正如您所知,MessageToDict()在没有我的指示下不会序列化默认值(就像在这个问题中:Protobuf doesn't serialize default values)。 所以我将参数including_default_value_fields=True添加到MessageToDict()的调用中:

protobuf.MessageToDict(example_message, including_default_value_fields=True)

返回:

{}

而不是我所期望的:

{'subMessage': {'number': 0}}

protobuf代码中的一条注释(可在此处找到:https://github.com/protocolbuffers/protobuf/blob/master/python/google/protobuf/json_format.py)证实了这种行为:

including_default_value_fields: If True, singular primitive fields, repeated fields, and map fields will always be serialized. If False, only serialize non-empty fields. Singular message fields and oneof fields are not affected by this option.

那么,我该怎么做才能得到一个包含所有值的dict,即使它们是嵌套消息中的默认值?在


有趣的是,当我的example.json看起来像这样:

{
    "subMessage" : {
        "number" : 0
    }
}

我得到了预期的输出。 但是我不能确保example.json将写出所有值,因此这不是一个选项。在


Tags: 信息jsontrueformatdefaultnumbermessagefields
1条回答
网友
1楼 · 发布于 2024-06-28 19:18:53

基于Looping over Protocol Buffers attributes in Python的答案,我创建了一个自定义MessageToDict函数:

def MessageToDict(message):
    messageDict = {}

    for descriptor in message.DESCRIPTOR.fields:
        key = descriptor.name
        value = getattr(message, descriptor.name)

        if descriptor.label == descriptor.LABEL_REPEATED:
            messageList = []

            for subMessage in value:
                if descriptor.type == descriptor.TYPE_MESSAGE:
                    messageList.append(MessageToDict(subMessage))
                else:
                    messageList.append(subMessage)

            messageDict[key] = messageList
        else:
            if descriptor.type == descriptor.TYPE_MESSAGE:
                messageDict[key] = MessageToDict(value)
            else:
                messageDict[key] = value

    return messageDict

给定从空example.json读取的消息,此函数返回:

^{pr2}$

相关问题 更多 >