protobuf与json转换小结

protobuf与json转换小结是一个比较常见的问题,在这里我将为你提供一个完整的攻略。

protobuf与json转换小结是一个比较常见的问题,在这里我将为你提供一个完整的攻略。

什么是protobuf

Protobuf(Protocol Buffers)是Google开发的一种轻便、高效、通用的数据序列化格式,可以用于数据存储、RPC(Remote procedure call)和数据交换等领域。它与XML和JSON等其他序列化格式相比,更为紧凑、快速,而且具有更好的性能。

在使用Protobuf前,需要定义一个.proto文件,该文件定义了要序列化的数据结构和数据类型。在定义好.proto文件的所有内容后,通过利用ProtoBuf中的编译器生成所需的数据对应的代码,进而在代码中调用对应接口进行数据序列化和反序列话操作。

protobuf与json之间的转换

Protobuf和JSON之间的转换非常常见,下面是protobuf和JSON之间转换的两种方式:

第一种方式:使用protobuf自带的JsonFormat工具

protobuf在自己的库中提供了JsonFormat工具,可以在protobuf和JSON之间进行转换,下面是转换的示例:

定义.proto文件

syntax = "proto3";

package tutorial;

message Person {
  string name = 1;
  int32 id = 2;  // Unique ID number for this person.
  string email = 3;

  enum PhoneType {
    MOBILE = 0;
    HOME = 1;
    WORK = 2;
  }

  message PhoneNumber {
    string number = 1;
    PhoneType type = 2;
  }

  repeated PhoneNumber phones = 4;
}

生成对应的数据结构

通过proto文件生成对应的数据结构:

protoc --proto_path=. --python_out=. ./person.proto

生成person_pb2.py文件,包含了所有protobuf数据对应的Python类

protobuf数据序列化为JSON字符串

import json
from google.protobuf.json_format import MessageToJson
from tutorial.person_pb2 import Person, PhoneNumber

def protobuf_to_json():
  person = Person()
  person.name = "John Doe"
  person.id = 1234
  person.email = "jdoe@example.com"
  phone = PhoneNumber()
  phone.number = "555-4321"
  phone.type = Person.HOME
  person.phones.append(phone)

  # 将protobuf数据转换为JSON字符串
  json_str = MessageToJson(person)
  print(json_str)

执行代码生成的JSON字符串为:

{
  "name": "John Doe",
  "id": 1234,
  "email": "jdoe@example.com",
  "phones": [
    {
      "number": "555-4321",
      "type": "HOME"
    }
  ]
}

JSON字符串反序列化为protobuf数据

def json_to_protobuf():
  json_str = """
  {
    "name": "John Doe",
    "id": 1234,
    "email": "jdoe@example.com",
    "phones": [
      {
        "number": "555-4321",
        "type": "HOME"
      }
    ]
  }
  """

  # 将JSON字符串转换为protobuf数据
  person = Person()
  json_format.Parse(json_str, person)
  print(person.name, person.id, person.email, person.phones[0].number, person.phones[0].type)

第二种方式:手动转换

不使用protobuf自带的工具,而是使用Python中自带的json库、protobuf库中自带的编码和解码方法手动转换。下面是手动转换的示例:

protobuf数据序列化为JSON字符串

def protobuf_to_json2():
  person = Person()
  person.name = "John Doe"
  person.id = 1234
  person.email = "jdoe@example.com"
  phone = PhoneNumber()
  phone.number = "555-4321"
  phone.type = Person.HOME
  person.phones.append(phone)

  # 手动序列化:protobuf数据转换为Python字典
  person_dict = {
    "name": person.name,
    "id": person.id,
    "email": person.email,
    "phones": [{
      "number": p.number,
      "type": p.type
    } for p in person.phones]
  }

  # 将Python字典转换为JSON字符串
  json_str = json.dumps(person_dict, indent=2)
  print(json_str)

执行代码生成的JSON字符串为:

{
  "name": "John Doe",
  "id": 1234,
  "email": "jdoe@example.com",
  "phones": [
    {
      "number": "555-4321",
      "type": "HOME"
    }
  ]
}

JSON字符串反序列化为protobuf数据

def json_to_protobuf2():
  json_str = """
  {
    "name": "John Doe",
    "id": 1234,
    "email": "jdoe@example.com",
    "phones": [
      {
        "number": "555-4321",
        "type": "HOME"
      }
    ]
  }
  """

  # 将JSON字符串转换为Python字典
  person_dict = json.loads(json_str)

  # 手动反序列化:Python字典转换为protobuf数据
  person = Person()
  person.name = person_dict["name"]
  person.id = person_dict["id"]
  person.email = person_dict["email"]
  for phone_dict in person_dict["phones"]:
    phone = person.phones.add()
    phone.number = phone_dict["number"]
    phone.type = getattr(Person.PhoneType, phone_dict["type"])

  print(person.name, person.id, person.email, person.phones[0].number, person.phones[0].type)

总结

以上就是protobuf和JSON之间转换的两种方式。如果你了解了protobuf文件的定义和Python中使用Protobuf的基本知识,在protobuf和JSON之间进行转换并不会是一件难事。哪个转换方式更好,需要根据实际情况来选择,这里的示例只是展示了两种基本的转换方法,具体的应用需要根据实际情况进行选择。

本文标题为:protobuf与json转换小结

基础教程推荐