How to handle a Generic type object with protocol buffers in a .proto file?

I spent some time looking for an alternative to handle shared objects, I saw questions similar to mine, but not the way I expect? Protocol buffers have several scalar types that I can use, however they are mostly primitive. I want my message to be flexible and can have a field that is a list of some kind.

Say my .proto file looks like this:

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; } } 

And it will be good, and I will work, and I will have a list in which objects can be of any primitive type or can be List <someObject>. However, the problem here is that at any time when I needed to process a new type of object, I would need to edit my .proto file, recompile for C # and java (for this I need languages) ...

If protocol buffers cannot handle generic object types, is there another alternative? Any help on this is greatly appreciated.

+6
source share
3 answers

As Mark Gravell noted, protocol buffers do not process generics or inheritance.

+4
source

Although I'm late, just for the sake of a new audience, you can use bytes instead of an object, and it can be any object that you can serialize / de-serialize.

+3
source

It is possible to get universal message functionality, but when adding new types, you will need to rebuild the proto classes.

You use shell class

 message Wrapper { extensions 1000 to max; required uint32 type = 1; } 

Then add some types

 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; } 

See how we extend the Wrapper class in the classes that we want to keep the Wrapper class using the extension.

Now, an example of creating a Foo wrapped object. I use Python as this is the most concise form. Other languages ​​can do the same.

 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() 

And an example of deserialization

 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) 

Now, since you need a common collection, make Wrapper a repeating field for another message and voilΓ .

Of course, this is not a complete solution, a little more packaging is required to create this architecture. For more information, read about Protobuf extensions, especially nested ( https://developers.google.com/protocol-buffers/docs/proto#nested ) or google about sorting items.

+1
source

Source: https://habr.com/ru/post/924781/


All Articles