使用 protbuf3,如何表示类型"映射字符串(可能是自定义类型)"?



我正在尝试在客户和服务之间共享一个大型词典/地图。我需要能够双向设置值,并从字典/地图中删除值,而无需每次来回传递整个映射。

我知道我可以使用:

创建地图
map<string, CustomType> cells = 3;

(ProtoBuf3地图的文档)

我看到了在此处使用一种的sugention:https://github.com/google/protobuf/issues/1606

但是,该错误报告中建议的语法对我没有意义:

message Test1 {
 oneof a_oneof {
  int32 a = 1;
 }
}

我将如何测试?我将如何存储?

我会尝试创建类似的东西:

message None{}
message MaybeCustomType{
 oneof maybe{
   CustomType just = 1;
   None       none = 2;
 }
}

,但我根本不相信这是优雅而正确的解决方案。

我还考虑了完全更改我的架构。

map<string, CustomType> cells = 1;
repeated string deleted_cells = 2;

但是,我不喜欢该解决方案,因为它会产生不确定的情况。如果"单元格"映射和" deleted_cells"映射都出现一个名为" foo"的单元格会发生什么?此外,它将数据从计算中抽象出来。我希望能够将单元格通过一个修改并有可能决定删除单元的函数,因此在我看来,关于单元格删除的信息似乎很自然。

您的语言标签提到了Haskell,但我不确定您要使用哪种库来提供proto3支持,因此我将尝试提供一个通用的答案。

概述

您指出的线程建议将oneof与单个字段一起使用,因为可以表示null(实际上是缺少字段)。幸运的是,您无需为此目的创建None类型,因为它是内置在特定于语言的生成源文件中的。查看" One"的语言指南...

您可以使用特殊情况()或哪个方法(根据您选择的语言)检查单位中的哪个值(如果有)。

"如果有"部分是您要寻找的魔术。一个单一定义的生成的C 代码将提供一种特殊的oneof_name_case()方法,该方法将告诉您是否设置了其中一个字段...

OneOfNamecase Oneof_name_case()const:返回指示设置哪个字段的枚举。如果没有设置它们,则返回Oneof_name_not_set。

为Java代码生成了类似的方法:getOneofNameCase()返回ONEOFNAME_NOT_SET,如果设置了一个单一字段。

示例

从测试消息开始...

message Test1 {
    oneof single_field_oneof {
        int32 some_int = 1;
    }
}

如果您使用的是C ,则可以使用类似于以下代码来处理单个字段...

int main(int argc, char* argv[]) {
    Test1 test;
    // <Populate message somehow>
    if (test.single_field_case() == Test1::kSomeInt) {
        std::cout << "Field is set, value is " << test.some_int() << std::endl;
    } else {
        assert(test.single_field_case() == Test1::SINGLE_FIELD_NOT_SET);
        std::cout << "Field is not set" << std::endl;
    }
}

无论如何,正如我提到的,我不熟悉Haskell的特定proto3语言绑定,但是oneof功能在库中应具有类似的功能。

相关内容

最新更新