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