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生成器

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"] = "[email protected]"
    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"] = "[email protected]"
    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 = "[email protected]"
    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字符串打印輸出。

運行結果如下:

到此這篇關於python中protobuf和json互相轉換應用的文章就介紹到這瞭,更多相關python protobuf和json互相轉換內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!

推薦閱讀: