ProtoJSON 形式

Protobuf から JSON への変換ユーティリティの使用方法について説明します。

Protobuf は JSON で標準的なエンコーディングをサポートしており、標準の protobuf バイナリワイヤフォーマットをサポートしないシステムとのデータ共有を容易にします。

ProtoJSON 形式は protobuf ワイヤフォーマットほど効率的ではありません。コンバーターはメッセージのエンコードとデコードにより多くの CPU を使用し、(まれなケースを除き) エンコードされたメッセージはより多くのスペースを消費します。さらに、ProtoJSON 形式ではフィールド名と enum 値名がエンコードされたメッセージに含まれるため、後でそれらの名前を変更するのが非常に困難になります。フィールドを削除すると、パースエラーをトリガーする破壊的な変更となります。要するに、Google が ProtoJSON 形式ではなく、ほとんどすべてにおいて標準ワイヤフォーマットを使用することを好む理由はたくさんあります。

エンコーディングは、このトピックの後半にある表で型ごとに説明されています。

JSON エンコードされたデータをプロトコルバッファにパースする際、値が欠落しているか、その値が null である場合、対応するデフォルト値として解釈されます。単一フィールドの複数の値 (重複または同等の JSON キーを使用) は受け入れられ、バイナリ形式のパースと同様に最後の値が保持されます。すべての protobuf JSON パーサーの実装が準拠しているわけではなく、一部の非準拠の実装では代わりに重複キーが拒否される場合があることに注意してください。

プロトコルバッファから JSON エンコードされた出力を生成する場合、protobuf フィールドがデフォルト値であり、かつフィールドがフィールドの有無をサポートしていない場合、デフォルトでは出力から省略されます。実装によっては、デフォルト値を持つフィールドを出力に含めるオプションを提供できます。

値が設定されており、フィールドの有無をサポートしているフィールドは、デフォルト値であっても、常に JSON エンコードされた出力にフィールド値を含めます。例えば、optional キーワードで定義された proto3 フィールドはフィールドの有無をサポートしており、設定されている場合、常に JSON 出力に表示されます。protobuf のどのエディションでもメッセージ型フィールドはフィールドの有無をサポートしており、設定されている場合、出力に表示されます。Proto3 の暗黙的な有無のスカラーフィールドは、その型のデフォルト値に設定されていない場合にのみ JSON 出力に表示されます。

JSON ファイルで数値データを表現する場合、ワイヤからパースされた数値が対応する型に収まらない場合、C++ でその型にキャストした場合と同じ効果が得られます(例えば、64ビットの数値が int32 として読み取られると、32ビットに切り詰められます)。

以下の表は、JSON ファイルでのデータの表現方法を示しています。

ProtobufJSONJSON の例備考
messageobject{"fooBar": v, "g": null, ...}JSON オブジェクトを生成します。メッセージフィールド名は lowerCamelCase にマップされ、JSON オブジェクトキーになります。json_name フィールドオプションが指定されている場合、代わりにその指定された値がキーとして使用されます。パーサーは、lowerCamelCase 名 (または json_name オプションで指定されたもの) と元の proto フィールド名の両方を受け入れます。null はすべてのフィールドタイプで受け入れられる値であり、対応するフィールドタイプのデフォルト値として扱われます。ただし、json_name の値として null を使用することはできません。理由の詳細については、json_name の厳格な検証を参照してください。
enumstring"FOO_BAR"proto で指定された enum 値の名前が使用されます。パーサーは enum 名と整数値の両方を受け入れます。
map<K,V>object{"k": v, ...}すべてのキーは文字列に変換されます。
repeated Varray[v, ...]null は空のリスト [] として受け入れられます。
booltrue, falsetrue, false
stringstring"Hello World!"
bytesbase64 文字列"YWJjMTIzIT8kKiYoKSctPUB+"JSON 値は、標準の base64 エンコーディングでパディング付きで文字列としてエンコードされたデータになります。標準または URL セーフの base64 エンコーディング (パディングの有無にかかわらず) のいずれも受け入れられます。
int32, fixed32, uint32number1, -10, 0JSON 値は十進数になります。数値または文字列のいずれも受け入れられます。空の文字列は無効です。
int64, fixed64, uint64string"1", "-10"JSON 値は十進数の文字列になります。数値または文字列のいずれも受け入れられます。空の文字列は無効です。
float, doublenumber1.1, -10.0, 0, "NaN", "Infinity"JSON 値は数値、または特殊な文字列値 "NaN"、"Infinity"、"-Infinity" のいずれかになります。数値または文字列のいずれも受け入れられます。空の文字列は無効です。指数表記も受け入れられます。
Anyobject{"@type": "url", "f": v, ... }Any に特別な JSON マッピングを持つ値が含まれている場合、それは {"@type": xxx, "value": yyy} のように変換されます。それ以外の場合、値は JSON オブジェクトに変換され、実際のデータ型を示すために "@type" フィールドが挿入されます。
Timestampstring"1972-01-01T10:00:20.021Z"RFC 3339 を使用します。生成される出力は常に Z 正規化され、小数部は 0、3、6、または 9 桁を使用します。「Z」以外のオフセットも受け入れられます。
Durationstring"1.000340012s", "1s"生成される出力は、必要な精度に応じて、常に小数部を 0、3、6、または 9 桁含み、その後に接尾辞「s」が続きます。ナノ秒精度に収まる限り、任意の小数桁 (なしも含む) が受け入れられ、接尾辞「s」は必須です。
Structobject{ ... }任意の JSON オブジェクト。struct.proto を参照してください。
ラッパー型様々な型2, "2", "foo", true, "true", null, 0, ...ラッパーは、ラップされたプリミティブ型と同じ表現を JSON で使用しますが、null が許可され、データ変換および転送中に保持される点が異なります。
FieldMaskstring"f.fooBar,h"field_mask.proto を参照してください。
ListValuearray[foo, bar, ...]
Valuevalue任意の JSON 値。詳細については google.protobuf.Value を確認してください。
NullValuenullJSON null
Emptyobject{}空の JSON オブジェクト

JSON オプション

準拠する protobuf JSON 実装は、以下のオプションを提供できます

  • 常にフィールドの有無なしで出力する: フィールドの有無をサポートせず、デフォルト値を持つフィールドは、JSON 出力ではデフォルトで省略されます (例: 値が 0 の暗黙的な有無の整数、空文字列の暗黙的な有無の文字列フィールド、空のリピートおよびマップフィールド)。実装によっては、この動作を上書きし、デフォルト値を持つフィールドを出力するオプションを提供できます。

    v25.x の時点では、C++、Java、Python の実装は非準拠です。このフラグが proto2 の optional フィールドには影響するものの、proto3 の optional フィールドには影響しないためです。将来のリリースでの修正が計画されています。

  • 未知のフィールドを無視する: protobuf JSON パーサーは、デフォルトでは未知のフィールドを拒否すべきですが、パース時に未知のフィールドを無視するオプションを提供できます。

  • lowerCamelCase 名の代わりに proto フィールド名を使用する: デフォルトでは、protobuf JSON プリンターはフィールド名を lowerCamelCase に変換し、それを JSON 名として使用します。実装によっては、代わりに proto フィールド名を JSON 名として使用するオプションを提供できます。Protobuf JSON パーサーは、変換された lowerCamelCase 名と proto フィールド名の両方を受け入れる必要があります。

  • enum 値を文字列ではなく整数として出力する: デフォルトでは、enum 値の名前が JSON 出力で使用されます。代わりに、enum 値の数値を使用するオプションを提供できます。