Java读取及生成pb文件并转换jsonString

Java读取及生成pb文件并转换jsonString

  • 1. 效果图
  • 2. 原理
    • 2.1 Protocol Buffers是什么
    • 2.2 支持的语言
    • 2.3 根据.proto生成.java
    • 2.4 初始化及构建pb,读取,转jsonString
  • 3. 源码
    • 3.1 address.proto
    • 3.2 PbParseUtil.java
  • 参考

  1. 读取pb及生成pb文件
  2. pb文件转换jsonString
  3. 二进制pb转换jsonString
  4. 赋值(有空或者类型不对应会无法赋值及报错)

1. 效果图

Java读取及生成pb文件并转换jsonString_第1张图片

2. 原理

2.1 Protocol Buffers是什么

协议缓冲区是用于序列化结构化数据的与语言无关、与平台无关的可扩展机制。

协议缓冲区(Protocol Buffers又名protobuf)是 Google 的语言中立、平台中立、可扩展的 序列化结构化数据的机制 – 想想 XML,但更小、更快、 简单。只需定义一次数据的结构,然后就可以 使用特殊生成的源代码轻松编写和读取结构化数据,往返各种数据流并使用多种语言。

2.2 支持的语言

协议缓冲区目前支持Java,Python,Objective-C,中生成的代码 和C++。使用新的 proto3 语言版本,还可以使用 Kotlin, Dart,Go,Ruby,PHP和C#,还有更多的语言即将推出。

2.3 根据.proto生成.java

protoc -I=$SRC_DIR --java_out=$DST_DIR $SRC_DIR/addressbook.proto

2.4 初始化及构建pb,读取,转jsonString

标准消息方法:

  • isInitialized():检查是否已设置所有必填字段。
  • toString():返回消息的人类可读表示形式, 对于调试特别有用。
  • mergeFrom(Message other):(仅限构建器)合并 的内容 other 到此消息中,覆盖奇异标量字段,合并复合 字段,并连接重复字段。
  • clear():(仅限构建器)将所有字段清除回空状态。

解析和序列化:

  • byte[] toByteArray();:序列化消息并返回一个字节数组 包含其原始字节。
  • static Person parseFrom(byte[] data);:解析来自给定的消息 字节数组。
  • void writeTo(OutputStream output);:序列化消息并写入它 到一个 OutputStream.
  • static Person parseFrom(InputStream input);:读取和分析消息 从 InputStream.

3. 源码

3.1 address.proto

syntax = "proto3";

package tutorial;

option java_multiple_files = true;
option java_package = "com.example.tutorial.protos";
option java_outer_classname = "AddressBookProtos";

message Person {
  string name = 1;
  int32 id = 2;
  string email = 3;
  Geometry geometry=4;
  repeated PhoneNumber phones = 5;

  enum PhoneType {
    PHONE_TYPE_UNSPECIFIED = 0;
    PHONE_TYPE_MOBILE = 1;
    PHONE_TYPE_HOME = 2;
    PHONE_TYPE_WORK = 3;
  }

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

  message Geometry {
    repeated Point point=1;
  }

  message Point{
    double longitude = 1;
    double latitude = 2;
    double altitude = 3;
  }

}

message AddressBook {
  repeated Person people = 1;
}

3.2 PbParseUtil.java

package com.test.utils;

import com.example.tutorial.protos.AddressBook;
import com.example.tutorial.protos.Person;
import com.googlecode.protobuf.format.JsonFormat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;

/*************************************
 *Class Name: PbParseUtil
 *Description: 
 *@author: Seminar
 *@create: 2023/7/31
 *@since 1.0.0
 *************************************/
public class PbParseUtil {

    // 打印pb的所有字段
    static void Print(AddressBook addressBook) {
        for (Person person : addressBook.getPeopleList()) {
            System.out.println("Person ID: " + person.getId());
            System.out.println("  Name: " + person.getName());
            if (StringUtils.isNotEmpty(person.getEmail())) {
                System.out.println("  E-mail address: " + person.getEmail());
            }

            for (Person.PhoneNumber phoneNumber : person.getPhonesList()) {
                switch (phoneNumber.getType()) {
                    case PHONE_TYPE_MOBILE:
                        System.out.print("  Mobile phone #: ");
                        break;
                    case PHONE_TYPE_HOME:
                        System.out.print("  Home phone #: ");
                        break;
                    case PHONE_TYPE_WORK:
                        System.out.print("  Work phone #: ");
                        break;
                }
                System.out.println(phoneNumber.getNumber());
            }

            if (person.getGeometry() != null) {
                for (Person.Point point : person.getGeometry().getPointList()) {
                    System.out.println("lon: " + point.getLongitude() + ",lat: " + point.getLatitude() + ",alt: " + point.getAltitude());
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {

        // 协议缓冲区编译器生成的消息类都是 不可变 。消息对象一旦构造完成,就无法修改,
        // 要构造消息,必须首先构造一个 生成器,将要设置的任何字段设置为所选值,然后调用build() 方法。

        // 初始化方法1
        Person john = Person.newBuilder()
                .setId(1234)
                .setName("John Doe")
                .setEmail("[email protected]")
                .addPhones(
                        Person.PhoneNumber.newBuilder()
                                .setNumber("555-4321")
                                .setType(Person.PhoneType.PHONE_TYPE_HOME))
                .build();

        // 初始化方法2
        Person.Builder person = Person.newBuilder();
        person.setEmail("[email protected]");
        person.setName("Lucy");
        person.setId(1).addPhones(Person.PhoneNumber.newBuilder()
                .setNumber("12634524230")
                .setType(Person.PhoneType.PHONE_TYPE_MOBILE));


        // java pb转二进制
        byte[] personPb = john.toByteArray();

        // java pb转pb文件
        byte[] personPb2 = person.build().toByteArray();
        String pbFilePath = System.getProperty("user.dir") + File.separator + "person.pb";
        try (FileOutputStream fileWriter = new FileOutputStream(pbFilePath)) {
            fileWriter.write(personPb2);
        }

        // pb二进制转Java对象
        // pb文件转Java对象
        Person person1 = Person.parseFrom(personPb);
        Person person2 = Person.parseFrom(new FileInputStream(pbFilePath));

        // pb文件转Java对象
        Person.Builder person3 = Person.newBuilder();
        person3.mergeFrom(new FileInputStream(pbFilePath));
        // 某些字段没有的,需要单独设置
        Person.Geometry.Builder geometryBuilder = Person.Geometry.newBuilder();
        for (int i = 0; i < 3; i++) {
            geometryBuilder.addPoint(Person.Point.newBuilder().setLongitude(113.222222 + i * 1.5).setLatitude(40.1 + i * 0.89).setAltitude(40 + i * 0.45).build());
        }
        person3.setGeometry(geometryBuilder.build());

        System.out.println("person1 name: " + person1.getName());
        System.out.println("person2 name: " + person2.getName());
        System.out.println("person3 name: " + person2.getName());

        AddressBook address = AddressBook.newBuilder()
                .addPeople(person1).addPeople(person3).build();
        Print(address);

        // pb转jsonString
        String str = JsonFormat.printToString(address);
        System.out.println("jsonStr: " + str);
    }
}

参考

  • http://code.google.com/p/protobuf/
  • Java proto 如何生成和反序列化消息
  • pb文件读取:https://blog.csdn.net/feiying0canglang/article/details/126125854
  • pb文件转java对象:https://protobuf.dev/getting-started/javatutorial/

你可能感兴趣的:(JAVA,工具箱,java,开发语言,Javapb读取及转换json,ProtocolBuffers,pb)