python中protobuf和json互相转换应用处理方法
hsy12342611 人气:0在实际信息系统开发中,经常会用到各种各样的协议,网络协议常用的有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生成器
protobuf生成器可以通过源码编译得到,也可以下载别人编译好的应用程序
GitHub上下载地址如下
GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format
2.2 定义protobuf格式的应用协议
下面以公司为业务构造协议,举例如下:
message.proto
syntax = "proto3"; message Empty {} message Address { string province = 1; string city = 2; string county = 3; string detail = 4; } message Person { int32 id = 1; string name = 2; Sex sex = 3; Address addr = 4; string email = 5; string phone = 6; enum Sex { MAIL = 0; FEMAIL = 1; } } message Company { string name = 1; repeated Person employee = 2; }
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
调用举例如下:
#coding=utf-8 import message_pb2 from google.protobuf import json_format import json #json转PB def jsonToPB(): json_addr = {} json_addr["province"] = "shanxisheng" json_addr["city"] = "shangluoshi" json_addr["county"] = "luonanxian" json_addr["detail"] = "guchengzhenliyuancunsanzu" json_person = {} json_person["id"] = 9999 json_person["name"] = "liudehua" json_person["sex"] = 1 json_person["addr"] = json_addr json_person["email"] = "123456789@163.com" json_person["phone"] = "859348598948656" strjson = json.dumps(json_person, indent=4) print(strjson) json_to_pb = json_format.Parse(strjson, message_pb2.Person()) print(json_to_pb.SerializeToString()) if __name__ == "__main__": print("=============Json to PB==========") jsonToPB() #coding=utf-8 import message_pb2 from google.protobuf import json_format import json #json转PB def jsonToPB(): json_addr = {} json_addr["province"] = "shanxisheng" json_addr["city"] = "shangluoshi" json_addr["county"] = "luonanxian" json_addr["detail"] = "guchengzhenliyuancunsanzu" json_person = {} json_person["id"] = 9999 json_person["name"] = "liudehua" json_person["sex"] = 1 json_person["addr"] = json_addr json_person["email"] = "123456789@163.com" json_person["phone"] = "859348598948656" strjson = json.dumps(json_person, indent=4) print(strjson) json_to_pb = json_format.Parse(strjson, message_pb2.Person()) print(json_to_pb.SerializeToString()) if __name__ == "__main__": print("=============Json to PB==========") jsonToPB()
说明:如上先使用json.dumps将字典打包成json字符串,然后使用json_format.Parse将json字符串转换为ProtoBuf对象,然后将ProtoBuf对象序列化为字节流打印输出。
运行结果如下:
4. Protobuf转Json
调用代码如下:
#coding=utf-8 import message_pb2 from google.protobuf import json_format import json #PB转json字符串 def pbToJson(pb): strjson = json_format.MessageToJson(pb) print(strjson) def buildPB(): person = message_pb2.Person() person.id = 110 person.name = "Boss" person.addr.province = "anm" person.addr.city = "qiuchongtian" person.addr.county = "ABC" person.addr.detail = "123" person.sex = message_pb2.Person.Sex.MAIL person.email = "rulaifo@qq.com" person.phone = "75211234567890" #PB对象序列化为字节流 pb1 = person.SerializeToString() person1 = message_pb2.Person() #字节流流构造PB对象 person1.ParseFromString(pb1) com = message_pb2.Company() com.name = 'USA' idlist = [111, 222, 222] for id in idlist: per = com.employee.add() per.id = id print(com) print(person1) return person1 if __name__ == "__main__": #构造PB pb = buildPB() print("=============PB to Json==========") 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字符串打印输出。
运行结果如下:
加载全部内容