Java:JSON – > Protobuf和后向转换
我有一个现有的系统,它在GUI和服务器之间使用基于protobuf的通信协议。 现在我想添加一些持久性,但目前protobuf消息直接转换为第三方自定义对象。
有没有办法将原型消息转换为json ,然后可以将其保存到数据库。
注意:我不太喜欢将二进制protobuf写入数据库的想法,因为它有一天会变得不能与新版本向后兼容并以这种方式破坏系统。
我们目前正在使用protobuf-java-format将我们的Protobuf消息( Message
任何子类)转换为JSON格式,以通过我们的Web API发送。
简单地说:
JsonFormat.printToString(protoMessage)
我不太喜欢将二进制protobuf写入数据库的想法,因为它有一天会变得不能与新版本向后兼容并以这种方式破坏系统。
将protobuf转换为JSON进行存储,然后在加载时转换回protobuf 更有可能产生兼容性问题,因为:
- 如果执行转换的进程不是使用最新版本的protobuf模式构建的,那么转换将以静默方式删除该进程不知道的任何字段。 存储和装载两端都是如此。
- 即使使用最新的模式,JSON < - > Protobuf转换在存在不精确的浮点值和类似的极端情况时也可能是有损的。
- 与JSON相比,Protobufs实际上具有(略微)更强的向后兼容性保证。 与JSON一样,如果添加新字段,旧客户端将忽略它。 与JSON不同,Protobufs允许声明一个默认值,这可以使新客户端更容易处理原本缺少该字段的旧数据。 这只是一个小优势,但Protobuf和JSON具有相同的向后兼容性属性,因此您无法通过存储JSON获得任何向后兼容性优势。
尽管如此,有许多库用于将protobuf转换为JSON,通常构建在Protobufreflection界面上(不要与Javareflection界面混淆; Protobufreflection由com.google.protobuf.Message
界面提供) 。
正如在回答类似问题时所提到的 ,从v3.1.0开始,这是ProtocolBuffers的支持function。 对于Java,请包含扩展模块com.google.protobuf:protobuf-java-util并使用JsonFormat,如下所示:
JsonFormat.parser().ignoringUnknownFields().merge(json, yourObjectBuilder); YourObject value = yourObjectBuilder.build();
除了Ophir的回答,JsonFormat甚至可以在protobuf 3.0之前使用。 但是,这样做的方式有所不同。
在Protobuf 3.0+中,JsonFormat类是一个单例,因此执行类似下面的操作
String jsonString = ""; JsonFormat.parser().ignoringUnknownFields().merge(json,yourObjectBuilder);
在Protobuf 2.5+中,以下应该有效
String jsonString = ""; JsonFormat jsonFormat = new JsonFormat(); jsonString = jsonFormat.printToString(yourProtobufMessage);
这是我编写的教程的链接,该教程在TypeAdapter中使用JsonFormat类,可以注册到GsonBuilder对象。 然后,您可以使用Gson的toJson和fromJson方法将原型数据转换为Java并返回。
回复牛仔裤 。 如果我们在文件中有protobuf数据并想要将其解析为protobuf消息对象,请使用merge方法TextFormat类。 请参阅以下代码段:
// Let your proto text data be in a file MessageDataAsProto.prototxt // Read it into string String protoDataAsString = FileUtils.readFileToString(new File("MessageDataAsProto.prototxt")); // Create an object of the message builder MyMessage.Builder myMsgBuilder = MyMessage.newBuilder(); // Use text format to parse the data into the message builder TextFormat.merge(protoDataAsString, ExtensionRegistry.getEmptyRegistry(), myMsgBuilder); // Build the message and return return myMsgBuilder.build();
尝试JsonFormat.printer().print(MessageOrBuilder)
,它看起来很适合proto3。 然而,目前还不清楚如何将实际的protobuf
消息(在.proto文件中定义的java包中提供)转换为com.google.protbuf.Message对象。
对于protobuf 2.5,使用依赖项:
"com.googlecode.protobuf-java-format" % "protobuf-java-format" % "1.2"
然后使用代码:
com.googlecode.protobuf.format.JsonFormat.merge(json, builder) com.googlecode.protobuf.format.JsonFormat.printToString(proto)