31

マップタイプに関する公式ドキュメントには次のように書かれています:

map<key_type, value_type> map_field = N;

...ここで、key_type は任意の整数型または文字列型にすることができます (したがって、浮動小数点型とバイトを除く任意のスカラー型)。value_type は任意の型にすることができます。

map<string, repeated string>フィールドを定義したいのですが、私の では違法のようでlibprotoc 3.0.0、 と文句を言いExpected ">"ます。だから、繰り返される文字列をマップに入れる方法はあるのだろうか。

考えられる回避策は次のとおりです。

message ListOfString {
    repeated string value = 1;
}

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

しかし、ListOfStringここでは冗長に見えます。

4

2 に答える 2

19

同じニーズがあり、同じエラーが発生しました。これが可能だとは思いません。以下は、言語仕様からの関連する BNF 定義です。

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 "]" ] ";"

「繰り返し」キーワードは、フィールド定義にのみ表示されます。マップ定義には、繰り返しキーワードを含まない「タイプ」が必要です。

つまり、いくつかのオプションがあります。

  • あなたが示したように、繰り返される値の周りにラッパーを作成できます。
  • 人々が定義した古い方法でマップを定義する方法があります。これはより面倒ですが、同等です。これは言語ガイドの下位互換性のある例です。https://developers.google.com/protocol-buffers/docs/proto3#maps
        メッセージ MapFieldEntry {
          key_type キー = 1;
          繰り返された value_type 値 = 2;
        }
        繰り返し MapFieldEntry map_field = N;
        
    自分でデータをマップに変換する必要がありますが、これはほとんどの言語でかなり簡単です。Java の場合:
        List<MapFieldEntry> map_field = // protobuf からの既存のリスト。
        Map<key_type, List<value_type>> = map_field.stream()
            .collect(Collectors.toMap(kv -> kv.key, kv -> kv.value));
    
        
  • google.protobuf.ListValue を使用して ください https://developers.google.com/protocol-buffers/docs/reference/google.protobuf#listvalue これは、既知の型からの型指定されていないリスト コレクションです。
于 2017-01-09T16:54:38.573 に答える