後端的protobuf的java類轉換JSON傳輸到前端Dart後轉protobuf的dart類讀取
這個是我自己踩過的坑之一。因爲某些場景中需要直接把.proto生成的java類包裝成JSON通過HTTP請求返回給Dart。但是我試了很多種方式,發現都會出現奇怪的錯誤,但是網上沒找到比較好的解決方法。
最後還是自己各種嘗試後,試出來了一種可以在Dart識別出JSON中的proto類的數據的方式。
不過,這種場景終究是少數情況。我這裏protobuf除這個情況以外都是用UDP數據報傳輸的,然後再字節數組轉proto類。
這篇文章在"我的github筆記-Netty-個人Netty實戰筆記"也是有的
我自己試過用protobuf轉JSON的protobuf-java-format
和protobuf-java-util
來將protobuf轉成JSON然後傳輸到Dart。而且其實protobuf生成的Java類的toString(),我自己打印到控制檯,看着也是JSON格式的。這幾種JSON的方式我都試過了,但是直接這麼JSON後傳到Dart都會出現一些奇怪的錯誤。再者也試過一些其他的操作,這裏不一一列舉,最後還是轉成UTF-8編碼的String傳輸得以成功。
出現的錯誤比如有:Protocol message end-group tag did not match expected tag
、Protocol message tag had invalid wire type.
等。
-
Java後端(這裏不方便公開代碼,只大致描述)
-
testController.java
這裏假設你有一個Java類叫作ProtobufJavaPo,裏面存了protobuf序列化數據的String形式數據的List
// Controller @RestController public class testController{ @GetMapping("/getTest") public ProtobufJavaPo getTest() { ProtobufJavaPo protobufJavaPo = new ProtobufJavaPo(); //... 省略給protobufJavaPo裝填數據的過程 return protobufJavaPo; // 這些都是我自己捏造的,就大概這個意思 } }
-
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; }
-
-
Dart前端/移動端(同樣都是模擬的,講個大概)
-
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; } }
-
DartMess.dart
class DartMess { List<TestProtoDart> protoList; // TestProtoDart假設是.proto文件生成的dart類 }
-