Java reads and generates pb files and converts jsonString

  1. Read pb and generate pb file
  2. pb file conversion jsonString
  3. Binary pb conversion jsonString
  4. Assignment (if it is empty or the type does not correspond, it will fail to assign a value and report an error)

1. Rendering

insert image description here

2. Principle

2.1 What are Protocol Buffers

Protocol Buffers is a language-neutral, platform-neutral, extensible mechanism for serializing structured data.

Protocol Buffers (aka protobuf) is Google's language-neutral, platform-neutral, extensible mechanism for serializing structured data - think XML, but smaller, faster, and simpler. Define the structure of your data once, then use specially generated source code to easily write and read structured data, to and from various data streams and in multiple languages.

2.2 Supported languages

Protocol Buffers currently supports generated code in Java, Python, Objective-C, and C++. With the new proto3 language version, Kotlin, Dart, Go, Ruby, PHP and C# are also available, with many more languages ​​coming soon.

2.3 Generate .java based on .proto

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

2.4 Initialize and build pb, read, convert to jsonString

Standard message method:

  • isInitialized(): Checks if all required fields are set.
  • toString(): Returns a human-readable representation of the message, especially useful for debugging.
  • mergeFrom(Message other): (builders only) Merges the content of other into this message, overwriting singular scalar fields, merging composite fields, and concatenating repeated fields.
  • clear(): (builders only) Clears all fields back to an empty state.

Parse and serialize:

  • byte[] toByteArray();: Serializes the message and returns a byte array containing its original bytes.
  • static Person parseFrom(byte[] data);: Parses the byte array from the given message.
  • void writeTo(OutputStream output);: Serializes the message and writes it to an OutputStream.
  • static Person parseFrom(InputStream input);: Read and parse messages from InputStream.

3. Source code

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: <pb读取转换工具类>
 *@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);
    }
}

reference

Guess you like

Origin blog.csdn.net/qq_40985985/article/details/132019995