【问题标题】:How to handle the generic type Object with protocol buffers, in the .proto file?如何在 .proto 文件中处理带有协议缓冲区的泛型对象?
【发布时间】:2012-09-06 17:27:03
【问题描述】:

我花了一些时间寻找一些替代方法来处理通用对象,我看到了与我类似的问题,但没有我想的那么具体? 协议缓冲区有多种我可以使用的标量类型,但它们大多是原始的。 我希望我的消息是灵活的,并且能够有一个是某种列表的字段。

假设我的 .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;
      }
  } 

这很好,可以工作,而且我有一个列表,其中对象可以是任何原始类型,也可以是列表 。 但是 - 这里的问题是,任何时候我需要处理一种新类型的对象,我都需要编辑我的 .proto 文件,为 C# 和 java 重新编译(我需要它的语言)......

如果协议缓冲区不能处理通用对象类型,还有其他替代方案可以吗? 非常感谢您对此事的任何帮助。

【问题讨论】:

标签: object protocol-buffers generic-list


【解决方案1】:

正如上述 Marc Gravell 所述 - 协议缓冲区不处理泛型或继承。

【讨论】:

    【解决方案2】:

    虽然我迟到了,只是为了新观众, 您可以使用字节代替对象,并且可以是您可以序列化/反序列化的任何对象。

    【讨论】:

    • 好的,我们可以像字节一样映射它,但是我们如何在客户端处理它呢??
    • 客户端是存储它的那个。您可以将完全限定的类名作为 protobuf 属性之一
    【解决方案3】:

    实现通用消息功能是可能的,但添加新类型仍需要重建 proto 类。

    你使用包装类

    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。

    【讨论】:

      【解决方案4】:

      这里是protobuf 3 definition of Struct,它基本上使用oneof 来定义这种“通用”消息类型。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2023-03-13
        • 1970-01-01
        • 1970-01-01
        • 2017-05-02
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多