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)