阅读量:0
除了之前的 protobuf-java依赖之外,还需要引入 protobuf-java-uti 依赖:
<!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java</artifactId> <version>3.19.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util --> <dependency> <groupId>com.google.protobuf</groupId> <artifactId>protobuf-java-util</artifactId> <version>3.19.1</version> </dependency>
如果不使用protobuf提供的JSON API,而使用fastJson等,直接序列化 com.google.protobuf.Message proto对象,会报错。如果希望使用第三方的JSON API,可以重新定义一个实体类,抽取需要的字段。
一、注意默认值
官方字段默认值,使用时需要注意:
- 对于标量消息字段,一旦解析了消息,就无法判断字段是显式设置为默认值还是根本没有设置(例如布尔值是否设置为false):所以,在定义消息类型时应该记住这一点。例如,如果你不希望某些行为在默认情况下也发生,不要使用布尔值在设置为false时打开某些行为。
- 如果将标量消息字段设置为其默认值(显式设置),则该值将不会在网络上序列化。
- Json 转 proto 对象时,如果Json字符串中的设置为了默认值(显式设置),则该值将不会在网络上序列化。
1、protobuf对象 转 JSON串
// 接收数据反序列化:将字节数据转化为对象数据。 UserProtoBuf.User user = UserProtoBuf.User.parseFrom(byteData); // 1、proto 对象 转 Json //获取 Printer对象用于生成JSON字符串 JsonFormat.Printer printer = JsonFormat.printer(); String userJsonStr = printer.print(user);
Printer对象生成 JSON字符串时,支持设置一些功能方法。比如:
includingDefaultValueFields()
:表示 Json输出包含默认值(显示和隐式赋默认值)的字段。- preservingProtoFieldNames():表示使用.proto文件中定义的原始proto字段名而不是将其转换为lowerCamelCase输出。默认 lowerCamelCase的输出。
2、JSON串 转 protobuf对象
// 创建 proto 对象 UserProtoBuf.User.Builder userBuilder = UserProtoBuf.User.newBuilder(); // 2、Json 转 proto 对象 //获取 Parser对象用于解析JSON字符串 JsonFormat.Parser parser = JsonFormat.parser(); parser.merge(userJsonStr2, userBuilder);
Parser对象解析 JSON字符串时,支持设置一些功能方法。比如:
ignoringUnknownFields()
:表示如果 json 串中存在的属性,proto 对象中不存在,则进行忽略,否则会抛出 InvalidProtocolBufferException异常。
二、示例实战
proto文件内容如下:
syntax = "proto3"; //生成 proto java文件名(一般指定,文件名+自定义。如果不指定,默认时文件名+OuterClass) option java_outer_classname = "UserProtoBuf"; message User { int32 age = 1; int64 timestamp = 2; bool enabled = 3; float height = 4; double weight = 5; string userName = 6; string Full_Address = 7; }
1、使用 JsonFormat默认功能
import com.google.protobuf.util.JsonFormat; public class UserTest { public static void main(String[] args) throws Exception { // 将数据序列化 byte[] byteData = getClientPush(); System.out.println("获取到字节数据:byteData长度=" + byteData.length); System.out.println("==========="); /** * 接收数据反序列化:将字节数据转化为对象数据。 */ UserProtoBuf.User user = UserProtoBuf.User.parseFrom(byteData); System.out.println("==== get获取 user信息:======="); System.out.println("user信息: \n" + user); System.out.println("------------------"); System.out.println("getAge= " + user.getAge()); System.out.println("getTimestamp= " + user.getTimestamp()); System.out.println("getEnabled= " + user.getEnabled()); System.out.println("getHeight= " + user.getHeight()); System.out.println("getWeight= " + user.getWeight()); System.out.println("getUserName= " + user.getUserName()); System.out.println("getFullAddress= " + user.getFullAddress()); /** * proto 对象 转 Json互转 */ // 1、proto 对象 转 Json String userJsonStr = JsonFormat.printer() //.includingDefaultValueFields() // 表示 Json输出包含默认值(显示和隐式赋默认值)的字段。 .print(user); System.out.println("=====1、proto对象 转 Json字符串:======"); System.out.println("userJsonStr= " + userJsonStr); // 2、Json 转 proto 对象 String userJsonStr2 = "{\n" + " \"age\":18,\n" + " \"timestamp\":\"1698377283315\",\n" + " \"enabled\":false,\n" + " \"height\":1.8,\n" + " \"weight\":66.76,\n" + " \"userName\":\"赵云\"\n" + "}"; // 创建 proto 对象 UserProtoBuf.User.Builder userBuilder = UserProtoBuf.User.newBuilder(); JsonFormat.parser() //.ignoringUnknownFields() // 表示如果 json 串中存在的属性,proto 对象中不存在,则进行忽略,否则会抛出 InvalidProtocolBufferException异常 .merge(userJsonStr2, userBuilder); UserProtoBuf.User user1 = userBuilder.build(); System.out.println("=====2、Json 转 proto 对象:======"); System.out.println("user1信息: \n" + user1); System.out.println("------------------"); } /** * 模拟发送方,将数据序列化后发送 * * @return */ private static byte[] getClientPush() { // 按照定义的数据结构,创建一个对象。 UserProtoBuf.User.Builder user = UserProtoBuf.User.newBuilder(); user.setAge(18); user.setTimestamp(System.currentTimeMillis()); user.setEnabled(false); //user.setEnabled(true); //user.setHeight(1.88F); user.setWeight(66.76D); user.setUserName("赵云"); //user.setFullAddress("王者-打野"); /** * 发送数据序列化:将对象数据转化为字节数据输出 */ UserProtoBuf.User userBuild = user.build(); byte[] bytes = userBuild.toByteArray(); return bytes; } }
2、设置 JsonFormat处理功能
这里使用 JsonFormat的这两个方法。其他方法自行查看。
- Printer对象使用 includingDefaultValueFields()方法。
- Parser对象使用 ignoringUnknownFields()方法。
将上面这两个方法的注释打开,运行结果如下:
– 求知若饥,虚心若愚。