python中protobuf和json互相轉(zhuǎn)換應(yīng)用處理方法
在實(shí)際信息系統(tǒng)開(kāi)發(fā)中,經(jīng)常會(huì)用到各種各樣的協(xié)議,網(wǎng)絡(luò)協(xié)議常用的有http,tcp,udp等,傳輸數(shù)據(jù)格式協(xié)議有json,xml,TLV等。本節(jié)將給大家介紹一種節(jié)省帶寬數(shù)據(jù)協(xié)議,谷歌的ProtoBuf協(xié)議,該協(xié)議由于是開(kāi)源免費(fèi)的,有多種語(yǔ)言的調(diào)用接口,比如常見(jiàn)C,C++,java,Python,C#,PHP ... 所以國(guó)內(nèi)很多公司都在使用。
本人所在項(xiàng)目引擎使用C++語(yǔ)言開(kāi)發(fā),外部輸入的protobuf字節(jié)流在內(nèi)部都是使用C++來(lái)處理,上次客戶(hù)端想要用他們的數(shù)據(jù)來(lái)演示效果,讓我去客戶(hù)現(xiàn)處理客戶(hù)數(shù)據(jù),然后導(dǎo)入我們引擎進(jìn)行效果展示??蛻?hù)現(xiàn)場(chǎng)數(shù)據(jù)是excel文件,出差時(shí)沒(méi)有相關(guān)的處理工具,本人只好現(xiàn)場(chǎng)開(kāi)發(fā),提取客戶(hù)excel中的數(shù)據(jù),轉(zhuǎn)換成json,再轉(zhuǎn)換成我們引擎能夠識(shí)別的ProtoBuf字節(jié)流。所以在此記錄一下python中protobuf和json的相互轉(zhuǎn)換的處理方法。
protobuf目前有proto2和proto3兩個(gè)版本,本文所介紹的是基于proto3,在Python 3.6.9環(huán)境下運(yùn)行。
1.ProtoBuf中定義字段與各語(yǔ)言類(lèi)型對(duì)應(yīng)表

2.ProtoBuf使用方法
2.1 下載安裝protobuf生成器
protobuf生成器可以通過(guò)源碼編譯得到,也可以下載別人編譯好的應(yīng)用程序
GitHub上下載地址如下
GitHub - protocolbuffers/protobuf: Protocol Buffers - Google's data interchange format
2.2 定義protobuf格式的應(yīng)用協(xié)議
下面以公司為業(yè)務(wù)構(gòu)造協(xié)議,舉例如下:
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 生成協(xié)議調(diào)用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
說(shuō)明:
-I 或者 --proto_path用來(lái)指定proto接口定義文件所在路徑
--python_out表示生成Python調(diào)用的接口
--cpp_out表示生成C++調(diào)用的接口
2.4 調(diào)用
引入protobuf庫(kù)和2.3生成的接口,就可以進(jìn)行自己的業(yè)務(wù)開(kāi)發(fā)了
3. Json轉(zhuǎn)Protobuf
調(diào)用舉例如下:
#coding=utf-8
import message_pb2
from google.protobuf import json_format
import json
#json轉(zhuǎn)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轉(zhuǎn)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()說(shuō)明:如上先使用json.dumps將字典打包成json字符串,然后使用json_format.Parse將json字符串轉(zhuǎn)換為ProtoBuf對(duì)象,然后將ProtoBuf對(duì)象序列化為字節(jié)流打印輸出。
運(yùn)行結(jié)果如下:

4. Protobuf轉(zhuǎn)Json
調(diào)用代碼如下:
#coding=utf-8
import message_pb2
from google.protobuf import json_format
import json
#PB轉(zhuǎn)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對(duì)象序列化為字節(jié)流
pb1 = person.SerializeToString()
person1 = message_pb2.Person()
#字節(jié)流流構(gòu)造PB對(duì)象
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__":
#構(gòu)造PB
pb = buildPB()
print("=============PB to Json==========")
pbToJson(pb)說(shuō)明:程序中使用message_pb2.Person()初始化得到一個(gè)protobuf對(duì)象person,然后給對(duì)象person各個(gè)屬性賦值,然后將person序列化為pb1,使用message_pb2.Person()構(gòu)造另一個(gè)對(duì)象
person1,person1使用person序列化后的pb1初始化,此時(shí)person1和person具有相同的屬性。
使用message_pb2.Company()構(gòu)造一個(gè)公司對(duì)象com,然后給屬性賦值。最后使用json_format.MessageToJson將protobuf類(lèi)型的person對(duì)象轉(zhuǎn)化為json字符串打印輸出。
運(yùn)行結(jié)果如下:

到此這篇關(guān)于python中protobuf和json互相轉(zhuǎn)換應(yīng)用的文章就介紹到這了,更多相關(guān)python protobuf和json互相轉(zhuǎn)換內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
簡(jiǎn)單理解Python中的事件循環(huán)EventLoop
在 python 3中,加入了 asyncio 模塊,來(lái)實(shí)現(xiàn)協(xié)程,其中一個(gè)很重要的概念是事件循環(huán),本文我們就來(lái)自己實(shí)現(xiàn)一個(gè)相對(duì)簡(jiǎn)單的EventLoop,從而了解一下事件循環(huán)是如何進(jìn)行運(yùn)轉(zhuǎn)的吧2023-10-10
python基本算法之實(shí)現(xiàn)歸并排序(Merge sort)
這篇文章主要給大家介紹了關(guān)于python基本算法之實(shí)現(xiàn)歸并排序(Merge sort)的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-09-09
conda創(chuàng)建環(huán)境過(guò)程出現(xiàn)"Solving?environment:?failed"報(bào)錯(cuò)的詳細(xì)解
很長(zhǎng)一段時(shí)間沒(méi)用conda了,然后突然使用conda創(chuàng)建環(huán)境報(bào)錯(cuò),所以下面這篇文章主要給大家介紹了關(guān)于conda創(chuàng)建環(huán)境過(guò)程出現(xiàn)"Solving?environment:?failed"報(bào)錯(cuò)的詳細(xì)解決方法,需要的朋友可以參考下2022-11-11
十行Python3代碼實(shí)現(xiàn)去除pdf文件水印
pfd文檔一般無(wú)法直接去除水印,需要先將pfd文檔轉(zhuǎn)換成圖片,在逐一對(duì)圖片進(jìn)行水印去除操作,最后在把圖片插入到pdf文檔中,這樣就很繁瑣。本文將用十行Python3代碼輕輕松松實(shí)現(xiàn)PDF文件水印去除,快來(lái)了解一下吧2022-02-02
使用Django和Postgres進(jìn)行全文搜索的實(shí)例代碼
這篇文章主要介紹了使用Django和Postgres進(jìn)行全文搜索,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-02-02
Python實(shí)現(xiàn)字典按key或者value進(jìn)行排序操作示例【sorted】
這篇文章主要介紹了Python實(shí)現(xiàn)字典按key或者value進(jìn)行排序操作,結(jié)合實(shí)例形式分析了Python針對(duì)字典按照key或者value進(jìn)行排序的相關(guān)操作技巧,需要的朋友可以參考下2019-05-05
python日期時(shí)間轉(zhuǎn)為字符串或者格式化輸出的實(shí)例
今天小編就為大家分享一篇python日期時(shí)間轉(zhuǎn)為字符串或者格式化輸出的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-05-05
Python+Pygame實(shí)戰(zhàn)之實(shí)現(xiàn)小蜜蜂歷險(xiǎn)記游戲
這篇文章主要為大家介紹了如何利用Python中的Pygame模塊實(shí)現(xiàn)小蜜蜂歷險(xiǎn)記游戲,文中的示例代碼講解詳細(xì),對(duì)我們學(xué)習(xí)Python游戲開(kāi)發(fā)有一定幫助,需要的可以參考一下2022-08-08
python魔法方法-屬性訪(fǎng)問(wèn)控制詳解
下面小編就為大家?guī)?lái)一篇python魔法方法-屬性訪(fǎng)問(wèn)控制詳解。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2016-07-07

