1
votes

Protobuf et Python: Comment ajouter des messages dans le champ "Tout répétable"?

J'ai un message proto:

syntax = "proto3";

import "google/protobuf/any.proto";

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

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

Comment puis-je ajouter des messages Target dans Task.targets?

Dans la documentation officielle I ' J'ai trouvé des informations sur la façon d'attribuer une valeur à un seul Tout une valeur de type>, mais dans mon cas, j'ai répété le type de champ Any .

Modifier : Task.targets peut contenir différents types de cibles, c'est pourquoi le type Any est utilisé. Un seul message Target est juste pour un exemple reproductible minimal.


0 commentaires

4 Réponses :


-1
votes

J'ai une connaissance limitée du type any , mais je pense que cela pourrait être traité comme s'il s'agissait d'une liste répétée de Target messages.

Code Python:

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


2 commentaires

Un test simple donne une erreur: TypeError: Le paramètre de MergeFrom () doit être une instance de la même classe: google.protobuf.Any got Target


Il semble que vous deviez initialiser votre tableau Any , puis utiliser la méthode pack pour y ajouter des éléments. vérifiez ceci



-1
votes

Après avoir joué pendant un certain temps, j'ai décidé de réviser la solution qui utilise la répétition de Any. Et voici un conseil pour ceux qui sont restés coincés au même endroit: essayez d'utiliser des types spécifiques au lieu de Any .

Une solution de contournement pour ma situation consiste à créer des messages de types SpecificTargetSet1 , SpecificTargetSet2 , etc. , qui contiennent des cibles spécifiques. Le fichier proto Task ressemblerait à:

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

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

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

Fichier proto de l'ensemble cible:

message SpecificTargetSet1 {
    repeated SpecificTarget1 targets = 1;
}

Et maintenant, une tâche pourrait être créée de cette manière:

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

Je ne marque pas ma réponse comme correcte, car il ne s'agit que d'une solution de contournement.


0 commentaires

1
votes

Merci @Justin Schoen. Selon https://developers.google. com / protocol-buffers / docs / reference / java / com / google / protobuf / Any , vous devez d'abord créer un objet Any, puis Pack a Target (ou tout autre type d'objet) avant de l'ajouter au liste.

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


0 commentaires

1
votes

Après avoir cherché moi-même une réponse, j'ai trouvé ce fil de discussion le plus pertinent, je publierai donc ma solution ici si cela aide quelqu'un (mais en Java / Scala).

Si vous le souhaitez

XXX

et cibles peuvent être n'importe quelle valeur telle que (string, bool, int, etc.). Voici comment je l'ai fait dans 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()


0 commentaires