我花了一些时间寻找一些替代方法来处理通用对象,我看到了与我类似的问题,但没有我想的那么具体? 协议缓冲区有多种我可以使用的标量类型,但它们大多是原始的。 我希望我的消息灵活并且能够有一个作为某种列表的字段。
假设我的 .proto 文件如下所示:
message SomeMessage
{
string datetime = 1;
message inputData // This would be a list
{
repeated Object object = 1;
}
message Object
{
? // this need to be of a generic type - This is my question
// My work around - Using extentions with some Object
//List all primitive scalar types as optional and create an extension 100 to max;
}
message someObject //some random entity - for example, employee/company etc.
{
optional string name = 1; optional int32 id = 2;
}
extend Object
{
optional someObject obj = 101;
}
}
这很好,并且可以工作,并且我有一个列表,其中对象可以是任何原始类型,也可以是列表< someObject >。 然而,这里的问题是,任何时候我需要处理新类型的对象,我都需要编辑我的 .proto 文件,重新编译 C# 和 java(我需要它的语言)...
如果协议缓冲区无法处理通用对象类型,是否有其他替代方案可以? 非常感谢有关此事的任何帮助。
正如 Marc Gravell 上面所说 - Protocol Buffers 不处理泛型或继承。
虽然我迟到了,只是为了新观众, 您可以使用字节代替对象,并且可以是您可以序列化/反序列化的任何对象。
这是 Struct 的 protobuf 3 定义,它基本上使用
oneof
来定义此类“通用”消息类型。
可以实现通用消息功能,但添加新类型仍然需要重建原型类。
您使用包装类
message Wrapper {
extensions 1000 to max;
required uint32 type = 1;
}
然后添加一些类型
message Foo {
extend Wrapper {
optional Foo item = 1000;
}
optional int attr1_of_foo = 1;
optional int attr2_of_foo = 2;
optional int attr3_of_foo = 3;
}
message Bar {
extend Wrapper {
optional Bar item = 1001;
}
optional int attr1_of_bar = 1;
optional int attr2_of_bar = 2;
optional int attr3_of_bar = 3;
}
看看我们如何使用扩展在我们想要由 Wrapper 类存储的类中扩展 Wrapper 类。
现在,创建 Foo 包装对象的示例。我使用Python,因为它是最简洁的形式。其他语言也可以这样做。
wrapper = Wrapper()
wrapper.type = Foo.ITEM_FIELD_NUMBER
foo = wrapper.Extensions[Foo.item]
foo.attr1_of_foo = 1
foo.attr2_of_foo = 2
foo.attr3_of_foo = 3
data = wrapper.SerializeToString()
以及反序列化的示例
wrapper = Wrapper()
wrapper.ParseFromString(data)
if wrapper.type == Foo.ITEM_FIELD_NUMBER:
foo = wrapper.Extensions[Foo.item]
elif wrapper.type == Bar.ITEM_FIELD_NUMBER:
bar = wrapper.Extensions[Bar.item]
else:
raise Exception('Unrecognized wrapped type: %s' % wrapper.type)
现在,因为您想要通用集合,请将 Wrapper 设为其他消息的重复字段,然后瞧。
当然这不是完整的解决方案,这个架构需要更多的封装才能使其易于使用。有关更多信息,请阅读有关 Protobuf 扩展的信息,尤其是嵌套扩展 (https://developers.google.com/protocol-buffers/docs/proto#nested) 或 google 有关项目编组的信息。
如果 java 需要,这一步不只是为了正确的文档目的,因为在 PyObject 包装器上执行 call 能够将参数传递给对象本身(?)