'Modeling a generic / arbitrary structure of properties with Protobuf

Say I'm modeling a Business resource in Protobuf. It represents any generic kind of "Business" - a bakery, a restaurant, a bank, etc...

Concept, in JSON

In JSON I might model the structure as follows:

{
  id: "...",
  name: "...",
  address: "...",
  properties: { 
    type: "...",
    ...
  }

The properties attribute is a different structure for each type of business.

For a bakery it might be:

properties: {
  type: 'Bakery',
  serves_coffee: true,
  gluten_free: true
}

For a bank it might be:

properties: {
  type: "Bank",
  max_denomination_offered: 100000,
}

Protobuf

The main Business can be modeled as follows in Protobuf:

message Business {
  string id = 1;
  string name = 2;
  string address = 3;
  ??? properties = 4
}

How do I model a generic Properties message that can have varying shape?

Is there some sort of "generic" object I can use? Or do I have to create BankProperties, BakeryProperties, etc... and add them in as:

Google.Protobuf.WellKnownTypes.Any properties = 4;

Is there an established or well-accepted pattern for this sort of thing?

Thanks!



Solution 1:[1]

What will your receiving code do? If it only knows about specific kinds of Business anyway, it would make sense to just list them in the .proto:

message BakeryProperties {
  bool serves_coffee = 1;
  bool serves_cake = 2;
}

message BankProperties {
  int32 max_denomination = 1;
}

message Business {
  string id = 1;
  string name = 2;
  string address = 3;

  oneof details {
    BakeryProperties bakery = 100;
    BankProperties bank = 101;
  }
}

That way you get the actual benefits of a schema: any code that knows how do deal with bakeries, deals with them in the same way. If the code doesn't know about the particular type, it can still use the common properties.

But if you are just going to e.g. display the properties, maybe what you want is just a generic key-value mapping:

map<string,string> properties = 10;

or

message Property {
   string name = 1;
   oneof {
      string strvalue = 2;
      int32 intvalue = 3;
   }
}
repeated Property properties = 10;

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 jpa