87

我有一个protobuf在 Python 中使用的反序列化对象。当我打印该对象时,它看起来像一个 python 对象,但是当我尝试将其转换为时,json我遇到了各种各样的问题。

例如,如果我使用json.dumps()我得到的对象(从 protoc 生成的代码)不包含 _ dict _ 错误。

如果我使用 jsonpickle 我得到UnicodeDecodeError: 'utf8' codec can't decode byte 0x9d in position 97: invalid start byte.

下面的测试代码正在使用jsonpickle上面显示的错误。

if len(sys.argv) < 2:
    print ("Error: missing ser file")
    sys.exit()
else :
    fileLocation = sys.argv[1]

org = BuildOrgObject(fileLocation) 

org = org.Deserialize()


#print (org)
jsonObj = jsonpickle.encode(org)
print (jsonObj)
4

5 回答 5

184

我建议使用谷歌protobuf库中的 protobuf↔json 转换器:

from google.protobuf.json_format import MessageToJson

json_obj = MessageToJson(org)

您还可以将 protobuf 序列化为字典:

from google.protobuf.json_format import MessageToDict
dict_obj = MessageToDict(org)

请参阅 protobuf 包 API 文档:https ://developers.google.com/protocol-buffers/docs/reference/python/ (参见模块google.protobuf.json_format)。

于 2016-09-25T08:50:58.950 回答
14

如果您需要直接使用 json,请查看protobuf-to-json库,但您必须手动安装它。

但出于以下几个原因,我建议您使用protobuf-to-dict库:

  1. 它可以从 pypi 访问,因此您可以简单地pip install protobuf-to-dict或将其包含在requirements.txt
  2. dict可以转换为 json 并且可能比 json 字符串更有用
于 2016-04-13T03:28:46.847 回答
2

您也可以使用 SerializeToString。

org.SerializeToString()
于 2021-03-24T11:33:22.007 回答
0

这是我将 proto3 对象转换为 JSON 对象(即 Python 字典)的函数:

def protobuf_to_dict(proto_obj):
    key_list = proto_obj.DESCRIPTOR.fields_by_name.keys()
    d = {}
    for key in key_list:
        d[key] = getattr(proto_obj, key)
    return d

由于 Google protobuf 库中的转换器在某些情况下似乎不适用于 3.19 版本,因此该函数利用了每个 Protobuf 对象上存在的 Descriptor 类

在这里,getattr(obj, string_attribute)返回给定的值obj.attribute

于 2022-02-06T09:23:12.723 回答
0

如果您使用的是没有preserving_proto_field_name字段的旧版本:

from google.protobuf.json_format import MessageToJson
def proto_to_json(proto_obj):
    json_obj = MessageToJson(proto_obj):
    json_obj = MessageToJso, including_default_value_fields=True)
    # Change lowerCamelCase of google Json conversion to the snake_case as in original protobuf
    dict_obj = dict((re.sub(r'(?<!^)(?=[A-Z])', '_', k).lower(),v) for k, v in json.loads(json_obj).items())
    if hasattr(proto_obj, 'uuid'):
        dict_obj["uuid"] = proto_obj.uuid.encode("hex")
    return json.dumps(dict_obj, indent=4, sort_keys=True)
于 2022-01-31T10:58:08.077 回答