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)

Я не отмечаю свой ответ как правильный, так как это просто обходной путь.

Другие вопросы по тегам