← 記事一覧

CSV と XML を JSON に変換する方法

JavaScript、Python、ブラウザで CSV と XML を JSON に変換。array-of-objects マッピング、XML 属性の扱い、型強制のワナを解説。

CSV と XML はあちこちにあります —— スプレッドシートのエクスポート、レガシー API、企業フィードなど —— しかし現代のコードのほとんどは JSON を欲しがります。マッピング規則と落とし穴(CSV ではすべてが文字列;XML の属性と繰り返し要素は特別な扱いが必要)を理解すれば、変換は単純です。本ガイドは JavaScript、Python、ブラウザでの両方向の変換を扱います。

範囲: 本記事は CSV → JSON と XML → JSON を一か所にまとめた包括的な how-toです。XML 専門 —— 属性、テキストノード、繰り返し要素、ネームスペースを深掘り —— が必要なら XML から JSON への変換:属性、テキストノード、配列、ネームスペース を読んでください。逆方向は JSON から XML を参照。

CSV を JSON に変換

CSV ファイルはカンマ区切り値の行の集まりで、たいていは見出し行があります。自然な JSON 表現は、行ごとに 1 つのオブジェクトを持ち、見出しをキーにしたオブジェクトの配列です:

# CSV
id,name,active
1,Ada,true
2,Bob,false
// JSON
[
  { "id": "1", "name": "Ada", "active": "true" },
  { "id": "2", "name": "Bob", "active": "false" }
]

値はすべて文字列 である点に注意 —— CSV には型がありません。"1" を数値に、"true" を真偽値に変換するのは、意図的に行う別ステップの型変換です。

JavaScript で CSV を JSON に

信頼できてシンプルな CSV なら手動で split できますが、実際の CSV は引用付きフィールドにカンマや改行が含まれるので、本番では papaparse のようなまっとうな parser を使いましょう:

// 最小 parser —— 単純で引用なしの CSV にのみ安全
function csvToJson(csv) {
  const [header, ...rows] = csv.trim().split('\n');
  const keys = header.split(',');
  return rows.map((row) => {
    const values = row.split(',');
    return Object.fromEntries(keys.map((k, i) => [k, values[i]]));
  });
}

// 本番 —— 引用、内部カンマ、改行を扱う
import Papa from 'papaparse';
const result = Papa.parse(csvText, { header: true, dynamicTyping: true });
// dynamicTyping が自動で "1" → 1、"true" → true に変換

Python で CSV を JSON に

import csv, json

with open('data.csv', newline='') as f:
    rows = list(csv.DictReader(f))   # 見出しをキーにした dict のリスト

print(json.dumps(rows, indent=2))

XML を JSON に変換

XML はもっと厄介です。JSON にはない概念があるからです:属性、テキストノード、そして単発 vs 繰り返し要素。唯一「正しい」マッピングは存在しません。一つの規約を選び、それを一貫して適用しましょう。

<!-- XML -->
<user id="1">
  <name>Ada</name>
  <role>admin</role>
  <role>editor</role>
</user>
// 一般的な JSON マッピング
{
  "user": {
    "@id": "1",                    // 属性、@ プレフィックス
    "name": "Ada",                 // 単一の子 → 値
    "role": ["admin", "editor"]    // 繰り返しの子 → 配列
  }
}

JavaScript で XML を JSON に

import { XMLParser } from 'fast-xml-parser';

const parser = new XMLParser({ ignoreAttributes: false, attributeNamePrefix: '@' });
const obj = parser.parse(xmlString);
// ブラウザでは DOMParser を使って手動でノードツリーを歩いてもよい。

Python で XML を JSON に

import xmltodict, json

doc = xmltodict.parse(xml_string)   # 属性は "@name" キーになる
print(json.dumps(doc, indent=2))

気をつけるべきマッピングの落とし穴

  • 型は失われる。 CSV と XML の値は文字列として到着します。数値と真偽値は明示的にキャストしてください —— parser がやってくれていると仮定しないこと。
  • 単一 vs 繰り返し要素。 1 つの <role> は値になり、2 つあれば配列になる。コンシューマを驚かせないよう、あるフィールドを常に配列とするか決めましょう。
  • 属性 vs 子要素。プレフィックス規約を選び(一般的には @)、ドキュメント化してください。
  • 空値と空白。 空の XML 要素や末尾の CSV カンマは、parser によって null""、あるいはキー欠落を生むことがあります。

BOM とエンコーディングの癖

Excel や一部の Windows ツールからエクスポートされたファイルは UTF-8 BOM(0xEF 0xBB 0xBF)で始まります。パース前に剥がさないと、最初の見出し / 要素名にこっそり含まれてしまいます。RFC 8259 は JSON の先頭の BOM を禁止しているので、自作の変換器は入力から削除して、出力にコピーしないようにしましょう。

TSV vs CSV(とその他の区切り)

「CSV」は必ずしもカンマ区切りではありません。タブ区切り値(TSV)はエンジニアリングパイプラインでよく使われます。値の中にタブはほとんど出てこないので、引用処理を省けるからです。ヨーロッパ版 Excel のエクスポートはよく ; を使います。出力が変な 1 列に詰まっているように見えるなら、ファイルの区切りが parser の期待と違うということ —— 区切りを切り替えるか、自動検出するライブラリを使いましょう。

XML ネームスペース

XML 要素はネームスペースプレフィックスで修飾できます(例:<soap:Envelope>)。これは xmlns 宣言で束縛されます。JSON にはネームスペースの概念がないので、多くの変換器は次の三つのいずれかを取ります:プレフィックスをキーに残す("soap:Envelope")、剥がす、あるいは xmlns 宣言を @xmlns:* 属性として保持する。プレフィックスを残すのが唯一の無損失オプションです。詳細は XML から JSON への変換 を参照。

結果を検証し整形する

変換が終わったら、出力が整形式で読みやすいことを確認します:

よくある質問

CSV を JSON に変換するには?

CSV を行にパースし、各行を見出しキーのオブジェクトにマッピング —— Python では csv.DictReader、JavaScript では papaparse のようなライブラリ。値はすべて最初は文字列です;型変換は自分で。

なぜ CSV から変換した JSON はすべて文字列なのですか?

CSV は型なし —— 各フィールドはテキストです。型自動変換を有効にする(例:papaparse の dynamicTyping)か、パース後に数値と真偽値を明示的に変換してください。

XML を JSON に変換するとき、XML 属性はどう扱いますか?

多くの変換器は属性を @ のようなプレフィックス付きキーにマッピング(例:@id)します。規約を一つ選び、一貫して適用すれば、下流のコードがどこを見ればよいか分かります。

XML→JSON の出力がオブジェクトだったり配列だったりするのはなぜ?

単一の子要素は値に、繰り返し要素は配列にマッピングされます。コンシューマが一貫した形状を期待するなら、特定要素を常に配列として扱うよう parser を設定してください。

ブラウザで変換、検証、整形