• python中protobuf和json互相转换应用


          在实际信息系统开发中,经常会用到各种各样的协议,网络协议常用的有http,tcp,udp等,传输数据格式协议有json,xml,TLV等。本节将给大家介绍一种节省带宽数据协议,谷歌的ProtoBuf协议,该协议由于是开源免费的,有多种语言的调用接口,比如常见C,C++,java,Python,C#,PHP ... 所以国内很多公司都在使用。

          本人所在项目引擎使用C++语言开发,外部输入的protobuf字节流在内部都是使用C++来处理,上次客户端想要用他们的数据来演示效果,让我去客户现处理客户数据,然后导入我们引擎进行效果展示。客户现场数据是excel文件,出差时没有相关的处理工具,本人只好现场开发,提取客户excel中的数据,转换成json,再转换成我们引擎能够识别的ProtoBuf字节流。所以在此记录一下python中protobuf和json的相互转换的处理方法。

    protobuf目前有proto2和proto3两个版本,本文所介绍的是基于proto3,在Python 3.6.9环境下运行。

    目录

    1.ProtoBuf中定义字段与各语言类型对应表

     2.ProtoBuf使用方法

    2.1 下载安装protobuf生成器

    2.2 定义protobuf格式的应用协议

    2.3 生成协议调用api

    2.4 调用

    3. Json转Protobuf

    4. Protobuf转Json


    1.ProtoBuf中定义字段与各语言类型对应表

     2.ProtoBuf使用方法

    2.1 下载安装protobuf生成器

    protobuf生成器可以通过源码编译得到,也可以下载别人编译好的应用程序

    GitHub上下载地址如下

    GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format

    2.2 定义protobuf格式的应用协议

    下面以公司为业务构造协议,举例如下:

    message.proto

    1. syntax = "proto3";
    2. message Empty {}
    3. message Address {
    4. string province = 1;
    5. string city = 2;
    6. string county = 3;
    7. string detail = 4;
    8. }
    9. message Person {
    10. int32 id = 1;
    11. string name = 2;
    12. Sex sex = 3;
    13. Address addr = 4;
    14. string email = 5;
    15. string phone = 6;
    16. enum Sex {
    17. MAIL = 0;
    18. FEMAIL = 1;
    19. }
    20. }
    21. message Company {
    22. string name = 1;
    23. repeated Person employee = 2;
    24. }

    2.3 生成协议调用api

    在Python中,生成方式如下:

    /home/test/protobuf/bin/protoc -I=/home/test/Python  --python_out=/home/test/Python   message.proto

    或者

    /home/test/protobuf/bin/protoc --proto_path=/home/test/Python  --python_out=/home/test/Python   message.proto

    附C++生成方式如下:

    /home/test/protobuf/bin/protoc -I=/home/test/cpp  --cpp_out=/home/test/cpp   message.proto 

    或者
    /home/test/protobuf/bin/protoc --proto_path=/home/test/cpp  --cpp_out=/home/test/cpp   message.proto 

    说明:
    -I  或者  --proto_path用来指定proto接口定义文件所在路径

    --python_out表示生成Python调用的接口

    --cpp_out表示生成C++调用的接口

    2.4 调用

    引入protobuf库和2.3生成的接口,就可以进行自己的业务开发了

    3. Json转Protobuf

    调用举例如下:

    1. #coding=utf-8
    2. import message_pb2
    3. from google.protobuf import json_format
    4. import json
    5. #json转PB
    6. def jsonToPB():
    7. json_addr = {}
    8. json_addr["province"] = "shanxisheng"
    9. json_addr["city"] = "shangluoshi"
    10. json_addr["county"] = "luonanxian"
    11. json_addr["detail"] = "guchengzhenliyuancunsanzu"
    12. json_person = {}
    13. json_person["id"] = 9999
    14. json_person["name"] = "liudehua"
    15. json_person["sex"] = 1
    16. json_person["addr"] = json_addr
    17. json_person["email"] = "123456789@163.com"
    18. json_person["phone"] = "859348598948656"
    19. strjson = json.dumps(json_person, indent=4)
    20. print(strjson)
    21. json_to_pb = json_format.Parse(strjson, message_pb2.Person())
    22. print(json_to_pb.SerializeToString())
    23. if __name__ == "__main__":
    24. print("=============Json to PB==========")
    25. jsonToPB()

    说明:如上先使用json.dumps将字典打包成json字符串,然后使用json_format.Parse将json字符串转换为ProtoBuf对象,然后将ProtoBuf对象序列化为字节流打印输出。

    运行结果如下:

    4. Protobuf转Json

    调用代码如下:

    1. #coding=utf-8
    2. import message_pb2
    3. from google.protobuf import json_format
    4. import json
    5. #PB转json字符串
    6. def pbToJson(pb):
    7. strjson = json_format.MessageToJson(pb)
    8. print(strjson)
    9. def buildPB():
    10. person = message_pb2.Person()
    11. person.id = 110
    12. person.name = "Boss"
    13. person.addr.province = "anm"
    14. person.addr.city = "qiuchongtian"
    15. person.addr.county = "ABC"
    16. person.addr.detail = "123"
    17. person.sex = message_pb2.Person.Sex.MAIL
    18. person.email = "rulaifo@qq.com"
    19. person.phone = "75211234567890"
    20. #PB对象序列化为字节流
    21. pb1 = person.SerializeToString()
    22. person1 = message_pb2.Person()
    23. #字节流流构造PB对象
    24. person1.ParseFromString(pb1)
    25. com = message_pb2.Company()
    26. com.name = 'USA'
    27. idlist = [111, 222, 222]
    28. for id in idlist:
    29. per = com.employee.add()
    30. per.id = id
    31. print(com)
    32. print(person1)
    33. return person1
    34. if __name__ == "__main__":
    35. #构造PB
    36. pb = buildPB()
    37. print("=============PB to Json==========")
    38. pbToJson(pb)

    说明:程序中使用message_pb2.Person()初始化得到一个protobuf对象person,然后给对象person各个属性赋值,然后将person序列化为pb1,使用message_pb2.Person()构造另一个对象

    person1,person1使用person序列化后的pb1初始化,此时person1和person具有相同的属性。

    使用message_pb2.Company()构造一个公司对象com,然后给属性赋值。最后使用json_format.MessageToJson将protobuf类型的person对象转化为json字符串打印输出。

    运行结果如下:

  • 相关阅读:
    SpringBoot+PageHelper+Vue+Element从零开始实现分页功能(包含前后端源码)
    在物理机内的虚机创建进入容器,执行命令时提示权限不够
    不值得定律 —— 如何在纠结的世界 活出不纠结的人生
    图解LeetCode——793. 阶乘函数后 K 个零(难度:困难)
    洛谷基础题练习5
    记录第一个启动代码的诞生
    【深入浅出Java并发编程指南】「难点 - 核心 - 遗漏」让我们一起探索一下CyclicBarrier的技术原理和源码分析
    kyuubi的查询遇到的问题NoneType‘ object has no attribute ‘_getitem_‘
    《永劫无间》找不到ffmpeg.dll无法继续执行怎么办,永劫无间找不到ffmpeg.dll解决方案
    工程化实战 - 前端AST(进阶)
  • 原文地址:https://blog.csdn.net/hsy12342611/article/details/128108829