Можно ли назначить несколько разных типов значений одному полю в повторяющемся сообщении 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 для создания и отправки данных запроса.


person twentythousand    schedule 21.03.2021    source источник


Ответы (1)


Существует официальный способ добиться этого: 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 обычно включает URL-адрес типа type.googleapis.com
  • При использовании Any поля title/loc будут инкапсулированы во вложенный объект, а не в строку того же уровня.

E.g.:

1 {
  1: "type.googleapis.com/Title"
  2 {
    1: "the title"
  }
}
person Peter Wishart    schedule 22.03.2021