変更要約: 初版
6.2JSONの構築とYANG
JSONを「有効か無効か」を判定できる水準で読み書きし(オブジェクト{}と配列[]の別・末尾カンマ不可・キーは二重引用符・値の型の区別)、その上でYANGがcontainer/list/leafでデータの型と構造を定義する言語であることを、モデル駆動運用の利点として理解します。
RESTCONFやコントローラAPIとやり取りする以上、送るペイロードが有効なJSONでなければ、機器に届く前にリクエストが弾かれます。この節で身につけるのは「JSONとは何か」という説明ではなく、目の前の断片を見て有効/無効を即断し、無効なら1文字単位で直せる力です。そしてJSONがデータの入れ物であるのに対し、YANGはそこに何が入るべきかを定めた型定義です。両者を「どちらもデータの話」と混ぜると、「JSONで型を強制できる」という誤解に落ちます——実際には型と構造の保証を担うのがYANGであり、その恩恵でベンダ横断の一貫した自動化が成り立ちます。
6.2.1有効なJSONの構成規則
- オブジェクトは波括弧
{}でキーと値の対を並べ、配列は角括弧[]で値を順に並べる。両者は入れ子にでき、{"interfaces": [{"name": "Gi1", "enabled": true}, {"name": "Gi2", "enabled": false}]}のように「オブジェクトの中に配列、配列の中にオブジェクト」が標準形になる。開いた括弧と閉じた括弧の種類と数が一致していなければ無効で、{を]で閉じるのはよくある破綻。 - キーは必ず二重引用符で囲む(
{"name": "Gi1"}は有効・{name: "Gi1"}は無効)。JavaScriptのオブジェクトリテラルや Python の辞書は引用符なしキーや単一引用符を許すが、JSONは単一引用符を一切認めない——{'name': 'Gi1'}は無効である。この差はPythonのdictをそのまま文字列化して送ったときに起こりやすく、json.dumps()を通す理由でもある。 - 最後の要素の後ろにカンマを置いてはならない(末尾カンマは無効)。
{"a": 1, "b": 2,}や[1, 2, 3,]は構文エラーで、パーサは文書全体を拒否する。行を追加/削除して編集したペイロードで最も起きやすい破綻であり、「エディタでは1文字の違いだが、APIから見れば文書全体が無効」という点が重要。 - 値の型は区別される:文字列は二重引用符付き(
"1500")、数値は引用符なし(1500)、真偽値は小文字のtrue/false、空値はnullである。True/False(Python流の大文字始まり)やNoneはJSONとしては無効で、"1500"と1500は別の型として扱われるため、数値を期待するフィールドに引用符付きで送ると型エラーで拒否されうる。
6.2.2YANG:データモデルを定義する言語
- YANGは設定と状態データの構造・型・制約を定義する言語であり、それ自体はデータでも通信プロトコルでもない。同じYANGモデルをNETCONF(XMLで転送)とRESTCONF(JSON/XMLで転送)が共有するため、「モデル=何を扱うか」「プロトコル=どう運ぶか」が明確に分離される。この分離こそがモデル駆動プログラマビリティの核心。
- containerは関連する項目をまとめる入れ物(インスタンスは1つ・JSONのオブジェクトに対応)、listは同種の要素を複数持つ集合でキー(識別子)を持つ(JSONの配列に対応・例:インタフェースの集合を
nameで識別)、leafはそれ以上分解しない単一の値で型(string/uint32/boolean等)を持つ。この3語で階層のほぼすべてが表現される。 - YANGの利点は型と制約による事前の妥当性検証にある。
leaf mtu { type uint32; }と定義されていれば、"mtu": "large"のような値は機器に適用される前にモデル違反として拒否され、CLIのタイプミスが本番に届く事故を防げる。加えて標準モデル(IETF・OpenConfig)を使えばベンダ差を吸収でき、機器ごとにCLI文法を書き分ける必要が減る。
JSONの有効性は4点チェックで即断できます:(1)括弧の対応({}と[]の種類と数)→(2)キーが二重引用符か(単一引用符・裸のキーは無効)→(3)末尾カンマが無いか→(4)値の型(true/false/nullは小文字・数値に引用符を付けない)。YANGはcontainer=まとめる入れ物/list=キーを持つ複数要素/leaf=型を持つ単一の値の3語で読み、モデル(YANG)とプロトコル(NETCONF/RESTCONF)は別レイヤである点を必ず区別しましょう。
RESTCONF経由でインタフェース設定を投入するスクリプトが、機器に届く前に400 Bad Requestで弾かれると相談を受けたとします。ペイロードは { "ietf-interfaces:interface": { "name": "GigabitEthernet2", "description": 'uplink to core', "enabled": True, "mtu": "1500", } } でした。ここで「機器側のRESTCONF設定が悪い」と機器を疑うのは遠回りで、このペイロードは4か所でJSONとして無効または不適切です。第一にdescriptionの値が単一引用符で囲まれています——JSONは文字列を二重引用符でのみ表現するため、この時点で構文エラーです。第二にenabledの値がTrueと大文字始まりになっています。これはPythonの真偽値の書き方であり、JSONの真偽値は小文字のtrue/falseでなければなりません(同様にNoneではなくnull)。この2点はPythonのdictをそのままstr()で文字列化して送ったときに典型的に発生し、json.dumps()を通せば両方とも自動的に正される——ここが実務上の再発防止策です。第三に"mtu": "1500" は構文としては有効ですが型として不適切です。YANGモデルでleaf mtu { type uint32; } と定義されていれば、期待されるのは引用符の無い数値1500であり、文字列"1500"はモデル違反として拒否されえます——「JSONとして通る」と「モデルに適合する」は別の関門だという理解が、この設問群の核心です。第四に"mtu"の後ろの末尾カンマがあり、これだけでもパーサは文書全体を拒否します。したがって正しい修正は { "ietf-interfaces:interface": { "name": "GigabitEthernet2", "description": "uplink to core", "enabled": true, "mtu": 1500 } } です。さらに一段深く見ると、なぜこの構造なのかもYANGで説明できます——ietf-interfaces:interfaceはインタフェース1つ分の属性をまとめるcontainer的な入れ物であり、その中のname・description・enabled・mtuはそれぞれ型を持つleafです。複数インタフェースを一度に送るなら、キーnameで識別されるlistとしてJSONの配列で表現します。ここで「配列であるべき場所にオブジェクトを、オブジェクトであるべき場所に配列を」置くと、JSONとしては有効なのにモデル違反で拒否される——400が返ったときに構文の誤りかモデル不適合かを切り分けられることが、無駄な機器側調査を避ける鍵になります。
| 観点 | 無効/不適切な例 | 正しい形 | 弾かれ方 |
|---|---|---|---|
| キーの引用符 | `{name: "Gi1"}` / `{'name': "Gi1"}` | `{"name": "Gi1"}` | 構文エラー(文書全体を拒否) |
| 末尾カンマ | `{"a": 1, "b": 2,}` | `{"a": 1, "b": 2}` | 構文エラー(文書全体を拒否) |
| 真偽値・空値 | `"enabled": True` / `"vrf": None` | `"enabled": true` / `"vrf": null` | 構文エラー(未定義のトークン) |
| 数値の型 | `"mtu": "1500"`(YANGは`uint32`) | `"mtu": 1500` | JSONは通るがモデル違反で拒否 |
| 構造の対応 | `list`(複数)の位置にオブジェクトを置く | `[{...}, {...}]` の配列で表す | JSONは通るがモデル違反で拒否 |
ひっかけ: 「JSONでもキーを単一引用符で囲める/末尾カンマは許容される」は誤りです——どちらも構文エラーで文書全体が拒否されます(Pythonのdict表記と混同しやすいのでjson.dumps()を使う)。また「YANGはデータ転送プロトコル」も誤り=YANGはモデル(型と構造)を定義する言語で、運ぶのはNETCONF(XML)やRESTCONF(JSON/XML)です。さらに「JSONとして有効なら必ず機器に受理される」も誤り=構文の妥当性とモデル適合は別の関門で、"mtu": "1500" のような型不一致はモデル違反で拒否されえます。
6.2.3この節のまとめ
- 有効なJSONは括弧の対応・二重引用符のキー・末尾カンマ無し・小文字の
true/false/nullを満たす。単一引用符と末尾カンマは文書全体を拒否させる - YANGはモデル(型と構造)を定義する言語で、container=まとめる入れ物・list=キーを持つ複数要素・leaf=型を持つ単一の値。運搬はNETCONF/RESTCONFが担う
400を受けたら構文エラーかモデル不適合かを切り分ける——型("1500"対1500)や構造(オブジェクト対配列)の不一致はJSONとしては有効でも拒否される
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. RESTCONF でインタフェース設定を投入するスクリプトが、機器へ届く前に 400 Bad Request で拒否される。送信しているペイロードは `{ "ietf-interfaces:interface": { "name": "GigabitEthernet2", "enabled": True, "mtu": 1500, } }` である。まず修正すべき点として最も適切なものはどれか。
Q2. 同僚が「YANG を使えば設定データを機器へ転送できるので、NETCONF や RESTCONF は不要になる」と述べた。この理解に対する指摘として最も適切なものはどれか。
Q3. 複数のインタフェースを1回のリクエストでまとめて設定したい。YANG モデルではインタフェースが `name` をキーとする `list` として定義されている。JSON ペイロードの構造として最も適切なものはどれか。

