首页 > 解决方案 > 您可以为重复的 Protobuf 消息中的一个字段分配多个不同的值类型吗?

问题描述

我正在尝试对将音频文件上传到服务器的客户端进行逆向工程,然后在单独的请求中上传文件的元数据。元数据在 Protobuf 中被序列化,它使用相当简单和可读的结构。这是它之后的样子protoc --decode_raw

1 {
  1: "title"
  2: "This is the audio title"
}
1 {
  1: "tags"
  2 {
  }
}
1 {
  1: "loc"
  2: "This is the location"
}
1 {
  1: "transcription"
  2: "A transcript"
}
1 {
  1: "mapping"
  2 {
    1 {
      1: 6
      2 {
        3: 840
      }
    }
    2: 6
  }
}

它似乎只是字段的重复消息,1每次都包含一个键值对,但有时该值是一个字符串,有时它是一个更复杂的消息。2如果 Protobuf 只允许您在每个字段中使用一种值类型,他们如何将字符串和消息都分配给字段?如果我要制定自己的请求,我需要这样的东西:

message KeyValuePair {
    string key = 1;
    oneof value {
        string str_value = 2;
        MessageValue msg_value = 2;
    }
}

但这不起作用,因为Field number 2 has already been used in "package.name" by field "str_value". 有任何想法吗?我将使用 Python 创建和发送请求数据。

标签: protocol-buffersprotocproto3protobuf-python

解决方案


有一种官方方法可以实现这一点:google.protobuf.Any

如果 protobuf 模式在顶层定义了 any,例如:

message Root {
  repeated google.protobuf.Any value = 1;
}

message Title {
  string title= 2;
}

message Tags {
  string name = 1;
  repeated string tags = 2;
}

然后可以在列表中序列化任何 Protobuf 定义类型的消息。

但是,我不认为这是现有代码正在做的事情:

  • 的原始输出Any通常包括type.googleapis.com类型 url
  • 使用Any,title / loc 字段将被封装在嵌套对象中,而不是同一级别的字符串。

例如:

1 {
  1: "type.googleapis.com/Title"
  2 {
    1: "the title"
  }
}

推荐阅读