简体   繁体   English

Protobuf 和 Python:如何将消息添加到“可重复的任何”字段?

[英]Protobuf and Python: How to add messages to "repeatable Any" field?

I have a proto message:我有一个原始消息:

syntax = "proto3";

import "google/protobuf/any.proto";

message Task {
    repeated google.protobuf.Any targets = 1;
    // ...
}

message Target {
    string name = 1;
    // ...
}

How should I add Target messages into Task.targets ?我应该如何将 Target 消息添加到Task.targets

In official docs I've found info about how to assign value to a single Any type value, however in my case I have repeated Any field type.在官方文档中,我找到了有关如何为单个Any类型值赋值的信息,但是在我的情况下,我repeated Any字段类型。

Edit : Task.targets may contain different types of targets, that's why Any type is used.编辑Task.targets可能包含不同类型的目标,这就是使用Any类型的原因。 A single Target message is just for minimal reproducible example.单个Target消息仅用于最小的可重现示例。

Thanks @Justin Schoen.谢谢@Justin Schoen。 According to https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Any , you need to first create an Any object, then Pack a Target (or any other object type) before appending it to the repeated list.根据https://developers.google.com/protocol-buffers/docs/reference/java/com/google/protobuf/Any ,您需要先创建一个 Any 对象,然后打包一个 Target (或任何其他对象类型)在将其附加到重复列表之前。

from google.protobuf.any_pb2 import Any
task = Task()
target = Any()
target.Pack(Target())
task.targets.append(any)

After searching for an answer myself, I found this thread to be the most relevant so I'll post my solution here if it helps anyone (but in Java/Scala).在自己搜索答案后,我发现这个线程是最相关的,所以如果它对任何人有帮助,我会在这里发布我的解决方案(但在 Java/Scala 中)。

If you want如果你想

repeated google.protobuf.Any targets = 1;

and targets can be any value such as (string, bool, int, etc). targets可以是任何值,例如(string、bool、int 等)。 This is how I did it in scala/java:这就是我在 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()

I have limited knowledge of the any type, but I would think it could be treated as if it were a repeated list of Target messages.我对any类型的了解有限,但我认为可以将其视为repeatedTarget消息列表。

Python Code:蟒蛇代码:

task_targets = []
task_targets.append(<insert_pb2_import>.Target(name='test'))
return <insert_pb2_import>.Task(targets=task_targets)

After playing around some time I have decided to revise the solution that uses repeating Any.在玩了一段时间后,我决定修改使用重复 Any 的解决方案。 And here is an advice for those who got stuck in this same place: try to use specific types instead of Any .这里有一个给那些被困在同一个地方的人的建议:尝试使用特定类型而不是Any

A workaround for my situation is to create messages of types SpecificTargetSet1 , SpecificTargetSet2 , etc., that contain specific targets.针对我的情况的解决方法是创建包含特定目标的SpecificTargetSet1SpecificTargetSet2等类型的消息。 The Task proto file would look like: Task原型文件如下所示:

message Task {
    google.protobuf.Any target_set = 1;
}

Target set proto file:目标集原型文件:

message SpecificTargetSet1 {
    repeated SpecificTarget1 targets = 1;
}

And now a task could be created in such a way:现在可以通过以下方式创建任务:

target = Target()
target.name = "Some name"

target_set = SpecificTargetSet1()
target_set.targets.append(target)

task = Task()
task.target_set.Pack(target_set)

I do not mark my answer as correct, as it is just a workaround.我没有将我的答案标记为正确,因为这只是一种解决方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM