I'm trying to long-term serialize a bunch of objects related by a strong class hierarchy in java, and I'd like to use protocol buffers to do it due to their simplicity, performance, and ease of upgrade. However, they don't provide much support for polymorphism. Right now, the way I'm handling it is by having a "one message to rule them all" solution that has a required string uri field that allows me to instantiate the correct type via reflection, then a bunch of optional fields for all the other possible classes I could serialize, only one of which will be used (based on the value of the uri field). Is there a better way to handle polymorphism, or is this as good as I'm going to get?
Bookmark this question. Show activity on this post. I'm trying to long-term serialize a bunch of objects related by a strong class hierarchy in java, and I'd like to use protocol buffers to do it due to their simplicity, performance, and ease of upgrade. However, they don't provide much support for polymorphism.
Protocol Buffers (Protobuf) is a free and open-source cross-platform data format used to serialize structured data. It is useful in developing programs to communicate with each other over a network or for storing data.
Protocol Buffer (Protobuf) provides two simpler options for dealing with values that might be of more than one type. The Any type can represent any known Protobuf message type. And you can use the oneof keyword to specify that only one of a range of fields can be set in any message.
In proto3 the extend
keyword has been replaced. From the docs: If you are already familiar with proto2 syntax, the Any type replaces extensions.
syntax = "proto3"; import "google/protobuf/any.proto"; message Foo { google.protobuf.Any bar = 1; }
But beware: Any
is essentially a bytes blob. Most of the times it is better to use Oneof
:
syntax = "proto3"; message A { string a = 1; } message B { string b = 1; } message Foo { oneof bar { A a = 1; B b = 2; } }
There are a few techniques for implementing polymorphism. I try to cover them all here: Protocol Buffer Polymorphism
My preferred approach uses nested extensions:
message Animal { extensions 100 to max; enum Type { Cat = 1; Dog = 2; } required Type type = 1; } message Cat { extend Animal { required Cat animal = 100; // Unique Animal extension number } // These fields can use the full number range. optional bool declawed = 1; } message Dog { extend Animal { required Dog animal = 101; // Unique Animal extension number } // These fields can use the full number range. optional uint32 bones_buried = 1; }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With