protobuf对象与JSON相互转换

打印 上一主题 下一主题

主题 599|帖子 599|积分 1797

除了之前的 protobuf-java依赖之外,还须要引入 protobuf-java-uti 依赖:
  1.         <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java -->
  2.         <dependency>
  3.             <groupId>com.google.protobuf</groupId>
  4.             <artifactId>protobuf-java</artifactId>
  5.             <version>3.19.1</version>
  6.         </dependency>
  7.         <!-- https://mvnrepository.com/artifact/com.google.protobuf/protobuf-java-util -->
  8.         <dependency>
  9.             <groupId>com.google.protobuf</groupId>
  10.             <artifactId>protobuf-java-util</artifactId>
  11.             <version>3.19.1</version>
  12.         </dependency>
复制代码
如果不利用protobuf提供的JSON API,而利用fastJson等,直接序列化 com.google.protobuf.Message proto对象,会报错。如果希望利用第三方的JSON API,可以重新界说一个实体类,抽取须要的字段。
一、留意默认值

   官网文档:https://protobuf.dev/programming-guides/proto3/#default
  

官方字段默认值,利用时须要留意:

  • 对于标量消息字段,一旦剖析了消息,就无法判定字段是显式设置为默认值还是根本没有设置(例如布尔值是否设置为false):以是,在界说消息类型时应该记住这一点。例如,如果你不希望某些举动在默认情况下也发生,不要利用布尔值在设置为false时打开某些举动。
  • 如果将标量消息字段设置为其默认值(显式设置),则该值将不会在网络上序列化。
  • Json 转 proto 对象时,如果Json字符串中的设置为了默认值(显式设置),则该值将不会在网络上序列化。
1、protobuf对象 转 JSON串

  1. // 接收数据反序列化:将字节数据转化为对象数据。
  2. UserProtoBuf.User user = UserProtoBuf.User.parseFrom(byteData);
  3. // 1、proto 对象 转 Json
  4. //获取 Printer对象用于生成JSON字符串
  5. JsonFormat.Printer printer = JsonFormat.printer();
  6. String userJsonStr = printer.print(user);
复制代码
Printer对象天生 JSON字符串时,支持设置一些功能方法。好比:


  • includingDefaultValueFields():表示 Json输出包含默认值(表现和隐式赋默认值)的字段。
  • preservingProtoFieldNames():表示利用.proto文件中界说的原始proto字段名而不是将其转换为lowerCamelCase输出。默认 lowerCamelCase的输出。
2、JSON串 转 protobuf对象

  1. // 创建 proto 对象
  2. UserProtoBuf.User.Builder userBuilder = UserProtoBuf.User.newBuilder();
  3. // 2、Json 转 proto 对象
  4. //获取 Parser对象用于解析JSON字符串
  5. JsonFormat.Parser parser = JsonFormat.parser();
  6. parser.merge(userJsonStr2, userBuilder);
复制代码
Parser对象剖析 JSON字符串时,支持设置一些功能方法。好比:


  • ignoringUnknownFields():表示如果 json 串中存在的属性,proto 对象中不存在,则进行忽略,否则会抛出 InvalidProtocolBufferException异常。
二、示例实战

proto文件内容如下:
  1. syntax = "proto3";
  2. //生成 proto java文件名(一般指定,文件名+自定义。如果不指定,默认时文件名+OuterClass)
  3. option java_outer_classname = "UserProtoBuf";
  4. message User {
  5.   int32 age = 1;
  6.   int64 timestamp = 2;
  7.   bool enabled = 3;
  8.   float height = 4;
  9.   double weight = 5;
  10.   string userName = 6;
  11.   string Full_Address = 7;
  12. }
复制代码
1、利用 JsonFormat默认功能

  1. import com.google.protobuf.util.JsonFormat;
  2. public class UserTest {
  3.     public static void main(String[] args) throws Exception {
  4.         // 将数据序列化
  5.         byte[] byteData = getClientPush();
  6.         System.out.println("获取到字节数据:byteData长度=" + byteData.length);
  7.         System.out.println("===========");
  8.         /**
  9.          * 接收数据反序列化:将字节数据转化为对象数据。
  10.          */
  11.         UserProtoBuf.User user = UserProtoBuf.User.parseFrom(byteData);
  12.         System.out.println("==== get获取 user信息:=======");
  13.         System.out.println("user信息:     \n" + user);
  14.         System.out.println("------------------");
  15.         System.out.println("getAge=         " + user.getAge());
  16.         System.out.println("getTimestamp=   " + user.getTimestamp());
  17.         System.out.println("getEnabled=     " + user.getEnabled());
  18.         System.out.println("getHeight=      " + user.getHeight());
  19.         System.out.println("getWeight=      " + user.getWeight());
  20.         System.out.println("getUserName=        " + user.getUserName());
  21.         System.out.println("getFullAddress= " + user.getFullAddress());
  22.         /**
  23.          * proto 对象 转 Json互转
  24.          */
  25.         // 1、proto 对象 转 Json
  26.         String userJsonStr = JsonFormat.printer()
  27.                 //.includingDefaultValueFields() // 表示 Json输出包含默认值(显示和隐式赋默认值)的字段。
  28.                 .print(user);
  29.         System.out.println("=====1、proto对象 转 Json字符串:======");
  30.         System.out.println("userJsonStr=    " + userJsonStr);
  31.         // 2、Json 转 proto 对象
  32.         String userJsonStr2 = "{\n" +
  33.                 "    "age":18,\n" +
  34.                 "    "timestamp":"1698377283315",\n" +
  35.                 "    "enabled":false,\n" +
  36.                 "    "height":1.8,\n" +
  37.                 "    "weight":66.76,\n" +
  38.                 "    "userName":"赵云"\n" +
  39.                 "}";
  40.         // 创建 proto 对象
  41.         UserProtoBuf.User.Builder userBuilder = UserProtoBuf.User.newBuilder();
  42.         JsonFormat.parser()
  43.                 //.ignoringUnknownFields() // 表示如果 json 串中存在的属性,proto 对象中不存在,则进行忽略,否则会抛出 InvalidProtocolBufferException异常
  44.                 .merge(userJsonStr2, userBuilder);
  45.         UserProtoBuf.User user1 = userBuilder.build();
  46.         System.out.println("=====2、Json 转 proto 对象:======");
  47.         System.out.println("user1信息:        \n" + user1);
  48.         System.out.println("------------------");
  49.     }
  50.     /**
  51.      * 模拟发送方,将数据序列化后发送
  52.      *
  53.      * @return
  54.      */
  55.     private static byte[] getClientPush() {
  56.         // 按照定义的数据结构,创建一个对象。
  57.         UserProtoBuf.User.Builder user = UserProtoBuf.User.newBuilder();
  58.         user.setAge(18);
  59.         user.setTimestamp(System.currentTimeMillis());
  60.         user.setEnabled(false);
  61.         //user.setEnabled(true);
  62.         //user.setHeight(1.88F);
  63.         user.setWeight(66.76D);
  64.         user.setUserName("赵云");
  65.         //user.setFullAddress("王者-打野");
  66.         /**
  67.          * 发送数据序列化:将对象数据转化为字节数据输出
  68.          */
  69.         UserProtoBuf.User userBuild = user.build();
  70.         byte[] bytes = userBuild.toByteArray();
  71.         return bytes;
  72.     }
  73. }
复制代码

2、设置 JsonFormat处理功能

这里利用 JsonFormat的这两个方法。其他方法自行查看。


  • Printer对象利用 includingDefaultValueFields()方法。
  • Parser对象利用 ignoringUnknownFields()方法。
将上面这两个方法的解释打开,运行结果如下:

   – 求知若饥,虚心若愚。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

梦见你的名字

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表