Protobuf и Python: как добавить сообщения в поле "Любое повторяющееся"?
У меня есть прото сообщение:
syntax = "proto3";
import "google/protobuf/any.proto";
message Task {
repeated google.protobuf.Any targets = 1;
// ...
}
message Target {
string name = 1;
// ...
}
Как мне добавить целевые сообщения в Task.targets
?
В официальных документах я нашел информацию о том, как присвоить значение одному значению типа Any, однако в моем случае у меня есть repeated Any
тип поля.
Редактировать: Task.targets
могут содержать разные типы целей, поэтому Any
тип используется. Один Target
сообщение только для минимального воспроизводимого примера.
4 ответа
Спасибо @Justin Schoen. Согласно https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Any, вам нужно сначала создать объект Any, а затем упаковать цель (или любой другой тип объекта) перед добавлением в повторяющийся список.
from google.protobuf.any_pb2 import Any
task = Task()
target = Any()
target.Pack(Target())
task.targets.append(any)
После самостоятельного поиска ответа я обнаружил, что эта ветка наиболее актуальна, поэтому я опубликую здесь свое решение, если оно кому-нибудь поможет (но в Java/Scala).
Если хочешь
repeated google.protobuf.Any targets = 1;
а также
targets
может быть любым значением, например (string, bool, int и т. д.). Вот как я это сделал в scala/java:
val task = Task.newBuilder()
.addTargets(Any.pack(StringValue.of("iss")))
.addTargets(Any.pack(Int32Value.of(25544)))
.addTargets(Any.pack(DoubleValue.of(1004.882447947814)))
.addTargets(Any.pack(DoubleValue.of(84.90917890132)))
.addTargets(Any.pack(DoubleValue.of(14.620929684)))
.addTargets(Any.pack(StringValue.of("kilometers")))
.build()
У меня ограниченные знания any
типа, но я думаю, что это можно рассматривать как repeated
Список Target
Сообщения.
Код Python:
task_targets = []
task_targets.append(<insert_pb2_import>.Target(name='test'))
return <insert_pb2_import>.Task(targets=task_targets)
Поработав некоторое время, я решил пересмотреть решение, использующее повторение Any. И вот совет для тех, кто застрял в этом же месте: попробуйте использовать конкретные типы вместо Any
,
Обходной путь для моей ситуации - создавать сообщения типов SpecificTargetSet1
, SpecificTargetSet2
и т. д., которые содержат конкретные цели. Task
Файл прото будет выглядеть так:
message Task {
google.protobuf.Any target_set = 1;
}
Прото-файл набора целей:
message SpecificTargetSet1 {
repeated SpecificTarget1 targets = 1;
}
И теперь задача может быть создана таким образом:
target = Target()
target.name = "Some name"
target_set = SpecificTargetSet1()
target_set.targets.append(target)
task = Task()
task.target_set.Pack(target_set)
Я не отмечаю свой ответ как правильный, так как это просто обходной путь.