作者:回忆的沙漏2502890423 | 来源:互联网 | 2023-05-21 18:20
我有一个现有的系统,它在GUI和服务器之间使用基于protobuf的通信协议.现在我想添加一些持久性,但目前protobuf消息直接转换为第三方自定义对象.
有没有办法将原型消息转换为json,然后可以将其保存到数据库.
注意:我不太喜欢将二进制protobuf写入数据库的想法,因为它有一天会变得不能与新版本向后兼容并以这种方式破坏系统.
1> 小智..:
我们目前正在使用protobuf-java-format将我们的Protobuf消息(任何子类Message
)转换为JSON格式,以通过我们的Web API发送.
简单地说:
JsonFormat.printToString(protoMessage)
在新版本中,这似乎已更改为`JsonFormat.printer()。print(MessageOrBuilder)`。
2> Ophir Radnit..:
正如在回答类似问题时所提到的,从v3.1.0开始,这是ProtocolBuffers的支持功能.对于Java,请包含扩展模块com.google.protobuf:protobuf-java-util并使用JsonFormat,如下所示:
JsonFormat.parser().ignoringUnknownFields().merge(json, yourObjectBuilder);
YourObject value = yourObjectBuilder.build();
3> Kenton Varda..:
我不太喜欢将二进制protobuf写入数据库的想法,因为它有一天会变得与新版本不向后兼容并以这种方式破坏系统.
将protobuf转换为JSON进行存储,然后在加载时转换回protobuf 更有可能产生兼容性问题,因为:
如果执行转换的进程不是使用最新版本的protobuf架构构建的,那么转换将以静默方式删除该进程不知道的任何字段.存储和装载两端都是如此.
即使使用最新的模式,JSON <- > Protobuf转换在存在不精确的浮点值和类似的极端情况时也可能是有损的.
与JSON相比,Protobufs实际上具有(略微)更强的向后兼容性保证.与JSON一样,如果添加新字段,旧客户端将忽略它.与JSON不同,Protobufs允许声明一个默认值,这可以使新客户端更容易处理原本缺少该字段的旧数据.这只是一个小优势,但Protobuf和JSON具有相同的向后兼容性属性,因此您无法通过存储JSON获得任何向后兼容性优势.
尽管如此,有很多库可以将protobufs转换为JSON,通常建立在Protobuf反射界面上(不要与Java反射界面混淆; Protobuf反射由com.google.protobuf.Message
界面提供).
4> Moses..:
除了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();
这个用于PROTO到3.0+的JSON:`JsonFormat.printer().print(MessageOrBuilder)`
5> 小智..:
试试看JsonFormat.printer().print(MessageOrBuilder)
,它对proto3看起来不错。但是,目前尚不清楚如何将实际protobuf
消息(由我在.proto文件中定义的Java包提供)转换为com.google.protbuf.Message对象。