web-dev-qa-db-fra.com

Protobuf3: Comment décrire la carte d'une chaîne répétée?

Documentation officielle sur le type de carte dit:

map<key_type, value_type> map_field = N;

... où key_type peut être n'importe quel type intégral ou chaîne (donc, tout type scalaire à l'exception des types à virgule flottante et des octets). Le value_type peut être tout type .

Je veux définir un map<string, repeated string> champ, mais il semble illégal sur mon libprotoc 3.0.0, qui se plaint Expected ">". Je me demande donc s'il existe un moyen de mettre une chaîne répétée dans la carte.

Une solution de contournement possible pourrait être:

message ListOfString {
    repeated string value = 1;
}

// Then define:
map<string, ListOfString> mapToRepeatedString = 1;

Mais ListOfString ici semble redondant.

13
lz96

J'ai eu le même besoin et j'ai eu la même erreur. Je ne pense pas que ce soit possible. Voici les définitions BNF pertinentes de la spécification du langage.

https://developers.google.com/protocol-buffers/docs/reference/proto3-spec

messageType = [ "." ] { ident "." } messageName
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "["fieldOptions "]" ] ";"
type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64"
  | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64"
  | "bool" | "string" | "bytes" | messageType | enumType
messageName = ident
ident = letter { letter | decimalDigit | "_" }
field = [ "repeated" ] type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"

Le mot-clé "répété" n'apparaît que dans la définition du champ. La définition de la carte nécessite un "type", qui n'inclut pas le mot-clé répété.

Cela signifie qu'il existe plusieurs options.

  • Vous pouvez créer un wrapper autour de la valeur répétée comme vous l'avez indiqué.
  • Il y a l'ancienne façon dont les gens ont défini les cartes, ce qui est plus lourd mais équivalent. Ceci est l'exemple rétrocompatible du guide de langue. https://developers.google.com/protocol-buffers/docs/proto3#maps
     message MapFieldEntry {
     key_type key = 1; 
     répété value_type value = 2; 
    } 
     répété MapFieldEntry map_field = N; 
     
    Vous auriez besoin de convertir les données en carte vous-même, mais cela devrait être assez banal dans la plupart des langues. En Java:
     List <MapFieldEntry> map_field = // Liste existante de protobuf. 
     Map <key_type, List <value_type>> = map_field.stream () 
     .Collect (Collectors.toMap ( kv -> clé kv, kv -> valeur kv)); 
     
     
  • Utilisez google.protobuf.ListValue https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#listvalue Il s'agit d'une collection de listes non typées de leurs types bien connus.
10
Ashton Snelgrove

Pour les utilisateurs de golang, cela devrait être comme suit.

message ListOfString {
   repeated string what_ever_name = 1;
}

// Then define:
map<string, ListOfString> what_ever_name = 1;

N'oubliez pas what_ever_name devrait être le même aux deux endroits.

0
Viraths