変更要約: 初版
1.1データ形式とパース
JSON・YAML・XMLという3つのデータ交換形式の特徴と、それぞれをPythonのデータ構造(dict・list)へパースして値を取り出す判断を、「この応答/設定ファイルをどう読み、どこから値を取るか」「なぜ読み込みに失敗したか」という提示物の解釈・診断として学びます。
自動化の第一歩は、機器やAPIが返すデータを正しく読むことです。DevNetの現場では、記法そのものの暗記より「このAPI応答(JSON)から目的の値をどう取り出すか」「このplaybook(YAML)はなぜ読み込めないのか」を即座に判断できることが問われます。この節ではまず3つの形式の使い分けを押さえ、次にそれらをPythonのdict(キーと値の対応)とlist(順序付きの並び)へパースして、ネスト(入れ子)した構造から値を取り出す手順を、実際の応答を読む診断として学びます。
1.1.13つのデータ形式の特徴
- JSON=波括弧
{}のオブジェクト(キーと値の対)と角括弧[]の配列で構成する機械可読な形式。文字列は必ず二重引用符"..."で囲み、true/false/nullは小文字、末尾カンマは不可。REST APIの応答/要求ボディの事実上の標準で、{"name": "r1", "up": true}のように簡潔。 - YAML=インデント(空白)で階層を表す人間可読な形式。
key: valueと、行頭-で始まるリストを使う。タブ禁止(空白のみ)でインデント量が構造そのものになるため崩れやすい。Ansible playbookや各種設定ファイルで多用され、JSONのスーパーセット(JSONはそのまま有効なYAML)。 - XML=開始/終了タグ
<tag>...</tag>で要素を入れ子にする冗長だが厳格な形式。属性や名前空間を持てる。NETCONFの応答など、モデル駆動の機器管理で今も使われる。JSON/YAMLより人手で書く負担は大きいが、スキーマ検証との相性がよい。
1.1.2Pythonデータ構造へのパース
- JSON文字列は
json.loads(text)で、REST応答はrequestsのresp.json()でdict/listへ変換する。オブジェクト{}はdict、配列[]はlist、文字列/数値/真偽値はそれぞれPythonのstr/int・float/bool、nullはNoneになる。逆にPythonから文字列化するのはjson.dumps(obj)。 - YAMLは
yaml.safe_load(text)でPythonのdict/listへ読む(loadではなく安全なsafe_loadを使う)。ネストした値の取り出しはキーとインデックスの連鎖:data["devices"][0]["name"]は「devicesリストの先頭要素のname」。まず一番外側がdictかlistかを見極めるのがコツで、これを外すとKeyErrorやTypeErrorになる。
「JSONは{}=dict・[]=list・二重引用符必須・末尾カンマ不可」「YAMLはインデントで階層・タブ禁止・- がリスト」「XMLはタグ入れ子でNETCONFに残る」「resp.json()/json.loads/yaml.safe_loadでdict/listへ、null→None」が頻出。設問は多くが「この応答から値を取る式はどれか」「なぜ読み込みに失敗したか」の判断型で来ます。
同僚のスクリプトが「デバイス一覧から先頭ルータのGi0/0が有効かを表示する」はずが例外で落ちる、と相談されました。APIはこのJSONを返します:{"devices": [{"name": "r1", "interfaces": [{"name": "Gi0/0", "enabled": true}]}]}。まず構造を読むと、一番外側はdict、キーdevicesの値はlist、その先頭要素がルータのdict、そのinterfacesがまたlistです。したがって目的の値へはdata["devices"][0]["interfaces"][0]["enabled"]とキー→インデックス→キー→インデックス→キーで辿ります。同僚のコードはdata["devices"]["interfaces"]と書いており、listに対して文字列キーで添字したためTypeErrorになっていました——「一番外はdict、その中はlist」を見誤ったのが原因です。次に、同じ設定をYAMLで持っていた別チームがyaml.safe_loadで読むと値がまるごと1本の文字列になった、という相談も来ました。原因はインデントにタブが混じっていたこと(YAMLはタブ禁止)と、- name: Gi0/0の- の後の空白が抜けてリスト要素として解釈されなかったことでした。ここで正しい判断は「JSONに書き換えよう」ではなく、タブを空白に直しインデントを揃えることです。要するに、形式ごとの厳密な規則(JSONの二重引用符と末尾カンマ、YAMLの空白インデント)と、パース後がdictかlistかを一段ずつ確かめる読み方こそが、自動化スクリプトの不具合を最短で切り分ける鍵になります。
| 観点 | JSON | YAML | XML |
|---|---|---|---|
| 主眼 | 機械可読・簡潔 | 人間可読 | 厳格・検証向き |
| 階層の表現 | `{}`と`[]` | インデント(空白) | タグの入れ子 |
| つまずき | 末尾カンマ不可・二重引用符必須 | タブ禁止・`- `後の空白 | 閉じタグ/名前空間が冗長 |
| 主な用途 | REST APIボディ | Ansible/設定ファイル | NETCONF等 |
ひっかけ: 「JSONの配列[]はPythonのdictになる」は誤りです——[]はlist、{}がdictです。リストの要素は文字列キーではなく整数インデックスで取り出します(data["devices"][0])。また「YAMLはタブでインデントしてもよい」も誤り=タブは禁止で、崩れたインデントはyaml.safe_loadで意図しない文字列や構造になります。resp.json()が返すのは辞書とは限らず、応答が配列ならlistが返る点にも注意。
1.1.3この節のまとめ
- JSONは
{}=dict/[]=list・二重引用符必須・末尾カンマ不可、YAMLは空白インデント・タブ禁止、XMLはタグ入れ子でNETCONFに残る resp.json()/json.loads/yaml.safe_loadでPythonのdict/listへパースし、nullはNoneになる- ネストした値はキーとインデックスの連鎖で辿る(
data["devices"][0]["enabled"])。まず各段がdictかlistかを見極めるのが診断の要
進捗の記録にはログインが必要です。
理解度チェック
(軽い確認用)Q1. APIが`{"devices": [{"name": "r1", "interfaces": [{"name": "Gi0/0", "enabled": true}]}]}`というJSONを返した。これを`data`にパース済みとする。先頭デバイスのGi0/0が有効かを取り出す式として正しいものはどれか。
Q2. ある担当者のAnsible playbook(YAML)が`yaml.safe_load`で読み込むと期待したdict/listにならず、値が1本の文字列として返る。最初に確認・修正すべき点として最も適切なものはどれか。
Q3. 設定ファイルを次のJSONで書いたところ、パーサがエラーを返した:`{"vlan": 10, "name": "sales",}`。エラーの原因として最も適切なものはどれか。

