如何在 ProtoBuf 中有效地建模 HashMap/Dictionary
How to model HashMap/Dictionary in the ProtoBuf efficiently
我有一个由 .NET 代码序列化的 protobuf 文件,我想将它用于 Java。在 .NET 代码中,有 Dictionary 数据类型,原型架构类似于
message Pair {
optional string key = 1;
optional string value = 2;
}
message Dictionary {
repeated Pair pairs = 1;
}
正如Whosebug中描述的那样post
Dictionary in protocol buffers.
我可以使用 protoc 将 proto 文件编译成 Java 类 很好。我可以成功地将 protobuf 文件反序列化为 Java 个对象。唯一的问题是它 t运行 变成 Java 中 Pair 对象的 List 而不是 HashMap。当然,我仍然拥有所有数据,但是我无法像我喜欢的那样高效地访问数据。如果我有键的值,我必须遍历整个列表才能得到它对应的值。这似乎不是最佳选择。
我想知道是否有更好的方法来为 protobuf 中的 Dictionary/Map 数据类型建模。
谢谢
更新:
我尝试了 Jon Skeet 在地址簿示例中添加地图类型字段的建议,但仍然 运行 有问题。
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
map<string, string> mapdata = 5;
}
协议在编译时抛出错误
addressbook.proto:25:3: Expected "required", "optional", or "repeated".
addressbook.proto:25:6: Expected field name.
根据 Google protobuf 文档,proto 2 确实支持地图类型 https://developers.google.com/protocol-buffers/docs/proto#maps 。正如我引用的那样,
Maps cannot be repeated, optional, or required.
所以我真的不知道为什么protoc不能编译它。这里还有一个讨论。答案表明 map 只是 proto 3 的一个特性。这与 google 的文档相矛盾。
嗯,maps are already supported in "protobuf proper" as of v3.0。例如,您的原型实际上是:
message Dictionary {
map<string, string> pairs = 1;
}
好消息是,使用您定义的键和值字段,它与您现有的数据完全向后兼容:)
坏消息是我不知道protobuf-net是否支持它。如果您实际上并没有在 .NET 端使用 .proto
文件,而是以声明方式执行所有操作,您可以修改 .proto
文件,重新生成 Java 代码,然后去...
剩下的坏消息是地图是在 v3.0 中引入的,在撰写本文时仍在 alpha/beta 中。现在,根据您需要发布的时间,您可以决定押注 v3.0 在您需要时发布 - 在我看来,拥有良好的地图语法的好处非常重要。目前所做的大部分更改都是围绕新的 proto3 功能进行的 - 而映射也允许在 proto2 语法文件中......只是你需要 v3.0 编译器和运行时才能使用它们。
我有一个由 .NET 代码序列化的 protobuf 文件,我想将它用于 Java。在 .NET 代码中,有 Dictionary 数据类型,原型架构类似于
message Pair {
optional string key = 1;
optional string value = 2;
}
message Dictionary {
repeated Pair pairs = 1;
}
正如Whosebug中描述的那样post Dictionary in protocol buffers.
我可以使用 protoc 将 proto 文件编译成 Java 类 很好。我可以成功地将 protobuf 文件反序列化为 Java 个对象。唯一的问题是它 t运行 变成 Java 中 Pair 对象的 List 而不是 HashMap。当然,我仍然拥有所有数据,但是我无法像我喜欢的那样高效地访问数据。如果我有键的值,我必须遍历整个列表才能得到它对应的值。这似乎不是最佳选择。
我想知道是否有更好的方法来为 protobuf 中的 Dictionary/Map 数据类型建模。
谢谢
更新:
我尝试了 Jon Skeet 在地址簿示例中添加地图类型字段的建议,但仍然 运行 有问题。
message Person {
required string name = 1;
required int32 id = 2; // Unique ID number for this person.
optional string email = 3;
enum PhoneType {
MOBILE = 0;
HOME = 1;
WORK = 2;
}
message PhoneNumber {
required string number = 1;
optional PhoneType type = 2 [default = HOME];
}
repeated PhoneNumber phone = 4;
map<string, string> mapdata = 5;
}
协议在编译时抛出错误
addressbook.proto:25:3: Expected "required", "optional", or "repeated".
addressbook.proto:25:6: Expected field name.
根据 Google protobuf 文档,proto 2 确实支持地图类型 https://developers.google.com/protocol-buffers/docs/proto#maps 。正如我引用的那样,
Maps cannot be repeated, optional, or required.
所以我真的不知道为什么protoc不能编译它。这里还有一个讨论
嗯,maps are already supported in "protobuf proper" as of v3.0。例如,您的原型实际上是:
message Dictionary {
map<string, string> pairs = 1;
}
好消息是,使用您定义的键和值字段,它与您现有的数据完全向后兼容:)
坏消息是我不知道protobuf-net是否支持它。如果您实际上并没有在 .NET 端使用 .proto
文件,而是以声明方式执行所有操作,您可以修改 .proto
文件,重新生成 Java 代码,然后去...
剩下的坏消息是地图是在 v3.0 中引入的,在撰写本文时仍在 alpha/beta 中。现在,根据您需要发布的时间,您可以决定押注 v3.0 在您需要时发布 - 在我看来,拥有良好的地图语法的好处非常重要。目前所做的大部分更改都是围绕新的 proto3 功能进行的 - 而映射也允许在 proto2 语法文件中......只是你需要 v3.0 编译器和运行时才能使用它们。