日本語

開発者ツール · 構文コンバーター

JSON は有効な YAML ですか? YAML 1.2 の約束とその約束のどこが壊れるか

· 背景

json yaml データ形式

YAML フロー スタイル フレームの内側に収まり、外側に YAML のみの機能がある JSON ドキュメント
オリジナル ToolAcre ベクトル イラスト

YAML 1.2 は、すべての JSON ドキュメントが YAML ドキュメントでもあるように設計されています。そのため、JSON から YAML への変換は簡単に感じられます。この投稿では、仕様が実際に何を保証しているのか、そしてその約束が失敗するエッジケースについて説明します。

JSON を YAML ファイルに貼り付けて問題を解決する - なぜそれが機能するのか、そして一度はうまくいかなかったのか

通常の JSON オブジェクトを YAML ソース側に貼り付け、ToolAcre の YAML 1.2 JSON スキーマで読み取ることができます。中かっこ、括弧、引用符で囲まれたキー、文字列、数値、ブール値、および null は、同じプレーンな JavaScript 値になります。これが、境界がしばしば些細なものに感じられる理由の説明になります。

保証はパーサー固有のままである必要があります。 ToolAcre はタグを制限し、エイリアスとネストを制限し、入力制限を適用します。テキストは、より広範な YAML プロセッサーの下では有効ですが、JSON に見えるコアとは無関係の安全性または形状上の理由から、ここでは拒否されることがあります。

通常の JSON は、この YAML 1.2 リーダーを通じてロードされます。サポートされていない拡張機能は別の理由で失敗します

選択したスキーマは、文字列、数値、ブール値、null、配列、マッピングなどの JSON 形式の値を生成します。この配置により、句読点の置換ではなく、解析してからシリアル化することが可能になります。ソース コードは YAML 仕様のすべての文言や誤りを確立しているわけではないため、この記事では完全な準拠を主張するのではなく、テストされた動作を報告しています。

厳密モードでは、チルダ、空の値、および `0o755` は文字列のままです。これらは、JSON 自体には含まれない YAML トークンです。コアは、JSON 形式の出力を返しながら、それらを別の方法で解決します。

出荷されたスキーマは、仕様のエッジをすべて証明することなく、JSON 形式のデータと一致します。

重複する YAML マッピング キーは最後の値を保持しますが、警告が表示されます。他の場所での厳密な解釈はそれらを拒否する可能性があります。従来の YAML 1.1 リーダーは `NO` などの単語を別の方法で入力できますが、このリーダーは単語を文字列として保持します。これらの違いにより、広範な移植性に関する記述が複雑になります。

インデントとして使用されるタブはエラーを生成しますが、引用符で囲まれた JSON 文字列内のタブはエスケープされます。非常に深い値または大きすぎる値は、ローカルの安全上限に達する可能性があります。理論的な言語関係は実装の境界をオーバーライドしません。

重複キーと従来のパーサーの違いが相互運用性の境界に残る

この値パイプラインでは、その逆は明らかに間違っています。 YAML コメントには JSON 表現がなく、エイリアスは繰り返しデータに解決され、マルチドキュメント ストリームは配列になり、サポートされていないタグは拒否されます。ブロック スカラーは文字列になりますが、その表現は失われます。

サポートされている YAML ドキュメントであっても、有効な JSON に変換でき、同じ YAML テキストに戻ることはありません。データの等価性は通常の値では存続する可能性がありますが、コメント、アンカー、スペル、およびストリーム ID は存続しません。

これが変換に意味するもの — JSON から YAML へはスタイルの変更、YAML から JSON への変換は情報が失われる可能性があります

JSON-to-YAML は通常、JSON 形状の入力のスタイルとシリアル化の変更です。 YAML-to-JSON は、まず YAML 固有の構文を解釈し、次にその結果を JSON のより小さい値のモデルに投影します。方向は対称ではありません。

ToolAcre は、ネストされた値、Unicode、null、配列、およびあいまいな文字列を含む通常の JSON-to-YAML-to-JSON ドキュメントをテストします。これらのフィクスチャは、対象となるデータ クラスを証明するものであり、考えられるすべての JSON または YAML プロセッサ ペアを証明するものではありません。

うまくいった例: JSON ドキュメントが YAML としてロードされる - 同じ構造で、JSON ツールが停止する場所を示すために YAML のみの機能が追加されます。

`{"country":"NO","items":[1,null],"nested":{"ok":true}}` を YAML 入力として貼り付けます。厳密なリーダーは同じツリーを返します。 YAML コメントを追加すると、値は同じままになりますが、コメントは消えます。繰り返されるオブジェクトをアンカーとエイリアスに置き換えます。 JSON には、参照構文ではなくコピーが含まれるようになりました。

`---` と 2 番目のドキュメントを追加します。結果は警告付きのドキュメントの配列になります。 `!!binary` を追加します。制限された読者はそれを拒否します。各ステップは、無視されるプレゼンテーション、解決された構造、ストリーム規約、サポートされていないタイプなど、明確な境界をマークします。

これでカバーされないもの — スキーマレベルの互換性。タイムスタンプなどの YAML 型には対応する JSON がありません。

スキーマの互換性は、表面的な構文だけに関するものではありません。コアは Infinity または NaN を作成できますが、JSON は警告とともに null として書き込みます。タイムスタンプとバイナリ タグは、制限されたスキーマの下では変換されずに拒否されます。 ToolAcre は、YAML を安全な JSON 形状のデータに意図的に絞り込みます。

別の YAML 実装は追加の型をサポートする場合があります。そのため、それらの時点でプレーン JSON 値との互換性が低くなりますが、自動的に良くなったり悪くなったりするわけではありません。対象となる契約やセキュリティ要件に基づいて選択してください。

スキーマレベルの互換性には、この制限されたリーダーが制限または拒否する非有限値と一時タグが含まれます

通常の JSON 形式のデータは、この YAML 1.2 リーダーおよびライターをきれいに通過します。すべてのドキュメントまたはパーサーに関する広範な主張には、重複キー、スキーマ バージョン、タグ、およびリソース制限をカバーするフィクスチャが必要です。

構文コンバーターを使用して、実際のテキストをテストし、その警告を読みます。 「JSON は YAML」は、実際の境界を正確にするパーサー、スキーマ、およびサポートされていない機能に名前を付けた後でのみ、便利な省略表現として扱います。

移植性テストの場合、1 つのフィクスチャを完全に JSON の値モデル内に保持し、もう 1 つは YAML のみの機能を一度に 1 つ追加します。対象となる各コンシューマを通じて両方を実行します。 1 つ目は、実際的なサブセットの主張を測定します。 2 つ目は、コメント、エイリアス、ストリーム、タグ、またはスカラー ルールが分岐する場所を正確に識別します。この段階的な方法は、システムが実際に使用するパーサーに関連したエラーが発生するため、2 つの言語が抽象的なサブセットであるかどうかを尋ねるよりも有益です。