後端的protobuf的java類轉換JSON傳輸到前端Dart後轉protobuf的dart類讀取

後端的protobuf的java類轉換JSON傳輸到前端Dart後轉protobuf的dart類讀取

這個是我自己踩過的坑之一。因爲某些場景中需要直接把.proto生成的java類包裝成JSON通過HTTP請求返回給Dart。但是我試了很多種方式,發現都會出現奇怪的錯誤,但是網上沒找到比較好的解決方法。

最後還是自己各種嘗試後,試出來了一種可以在Dart識別出JSON中的proto類的數據的方式。

不過,這種場景終究是少數情況。我這裏protobuf除這個情況以外都是用UDP數據報傳輸的,然後再字節數組轉proto類。

這篇文章在"我的github筆記-Netty-個人Netty實戰筆記"也是有的

​ 我自己試過用protobuf轉JSON的protobuf-java-formatprotobuf-java-util來將protobuf轉成JSON然後傳輸到Dart。而且其實protobuf生成的Java類的toString(),我自己打印到控制檯,看着也是JSON格式的。這幾種JSON的方式我都試過了,但是直接這麼JSON後傳到Dart都會出現一些奇怪的錯誤。再者也試過一些其他的操作,這裏不一一列舉,最後還是轉成UTF-8編碼的String傳輸得以成功。

​ 出現的錯誤比如有:Protocol message end-group tag did not match expected tagProtocol message tag had invalid wire type.等。

  1. Java後端(這裏不方便公開代碼,只大致描述)

    1. testController.java

      ​ 這裏假設你有一個Java類叫作ProtobufJavaPo,裏面存了protobuf序列化數據的String形式數據的List

      // Controller
      @RestController
      public class testController{
          
          @GetMapping("/getTest")
          public ProtobufJavaPo getTest() {
              ProtobufJavaPo protobufJavaPo = new ProtobufJavaPo();
              //... 省略給protobufJavaPo裝填數據的過程
              return protobufJavaPo; // 這些都是我自己捏造的,就大概這個意思
          }
      
      }
      
    2. ProtobufJavaPo.java

      ​ 這裏假設你的.proto生成的java類爲TestProto.java,然後你用其Builder生成了對應的對象叫作testProto

      // 這裏用到了IDEA的Lombok插件
      @Data
      @EqualsAndHashCode(callSuper = false)
      @Accessors(chain = true)
      @JsonInclude(JsonInclude.Include.NON_NULL)
      public class ProtobufJavaPo implements Serializable {
          private static final long serialVersionUID = 1L;
      
          // protobuf序列化數據的 byte數組 使用UTF-8編碼 轉String
          // 這裏假設testProto就是.proto文件生成的java類的對象
          // udpProtoList.add(new String(testProto.toByteArray(), StandardCharsets.UTF_8));
          List<String> udpProtoList;
      }
      
  2. Dart前端/移動端(同樣都是模擬的,講個大概)

    1. HttpDart.dart

      ​ 這裏假設dart中,dart的.proto文件生成dart類爲TestProtoDart.dart。Dart識別HTTP中JSON數據的String形式的proto數據,並重新轉化成dart生成的TestProtoDart.dart。

      import 'package:dio/dio.dart';// 社區的http請求包。可以去(dev.pub)這個網站查找
      // 其餘依賴我就不說了
      // 這裏DartMess是假裝有這麼一個dart類作爲返回值,其含有List<TestProtoDart> protoList;
      class HttpDart {
      
          // HTTP獲取JSON數據,解析裏面的String字符串形式的protobuf數據
          // 然後轉成dart中.proto生成的TestProtoDart.dart類。(這些名稱什麼的全都假設的)
          Future<DartMess> getProtoFromJSON() async {
      
              var response = await dio.get('XXXXXXXX(host:port)/getTest');
              List dynamicList = response.data['udpProtoList'];
              if(dynamicList!=null){
                  var dartMess = DartMess(); 
                  List<TestProtoDart> protoDartList = List();
                  dynamicList.forEach((f)=>{protoDartList.add(TestProtoDart.fromBuffer(utf8.encode(f)))});
                  dartMess.protoList = protoDartList;
                  return dartMess;
              }
              return null;
          }
      }
      
    2. DartMess.dart

      class DartMess {
          List<TestProtoDart> protoList; // TestProtoDart假設是.proto文件生成的dart類
      }
      
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章