プログラミング

CSVファイルでJSON文字列を正しくエスケープする方法

「CSVファイルにダブルクォートを含むデータを書き込んだら、エラーになってしまった…」

「JSON文字列をCSVに変換したら、『Unexpected character』や『Invalid JSON format』というエラーが出て困っている…」

実はこの問題の原因は、CSVでのダブルクォーテーションのエスケープ方法を間違えていることなんです。

JSONではバックスラッシュ(\)でエスケープするのに、CSVでは全く違うルールが使われているため、多くの方が混乱してしまいます。

私も最初は「なんでJSONのエスケープが効かないんだ?」と悩みました。

本記事では、CSVファイル中でのダブルクォーテーションの正しいエスケープ方法を、具体例とともに分かりやすく解説します。

この記事を読めば、JSONのCSV化を含め、CSVファイル中でのダブルクォーテーションの扱いを完全に理解できるようになります!

JSONのエスケープ方法(\")はCSVでは使えない

CSVではダブルクォート(")が特別な意味を持つ文字です。

CSVパーサーは、ダブルクォートを見つけると「この中身は1つのフィールドだ」と判断します。

カンマや改行が含まれていても、ダブルクォートで囲まれた部分は1つのデータとして扱われます。

しかし、フィールド内にダブルクォートそのものを含めたい場合に問題が発生します。

普通にダブルクォートを書いてしまうと、CSVパーサーが「ここでフィールドが終わった」と勘違いしてしまい、エラーになってしまいます。

ここで多くの方が混乱するのが、JSONとCSVでエスケープ方法が全く違うことです。

JSONでは、ダブルクォートをエスケープする際にバックスラッシュを使います(例:\")。

しかし、CSVではこの方法が通用しません。

CSVパーサーは\"を見ても「エスケープされたダブルクォートだ」とは解釈してくれないため、JSONのエスケープ方法をそのまま使うと、エラーになってしまいます。

CSVではダブルクォートを2つ重ねてエスケープする("")

CSVでダブルクォートをエスケープする正しい方法は、ダブルクォート"を2つ重ねます。

1つのダブルクォート文字を表現したい場合は、""と書きます。

CSVパーサーは、この""を見つけると「これは1つのダブルクォート文字だ」と自動的に解釈します。

これは、CSV標準(RFC4180)で定められた正式なルールです。

また、フィールド内にカンマや改行が含まれている場合、そのフィールド全体をダブルクォートで囲む必要もあります。

この場合、フィールド内のダブルクォートは全て二重化します。例えば、「こんにちは"世界"」という文字列をCSVに書き込む場合、"こんにちは""世界"""と記述します。

JSON文字列の書き方:全体を囲み、内部のダブルクォートを二重化する

JSON文字列全体をダブルクォートで囲む

JSON文字列をCSVに変換する際は、まずJSON文字列全体をダブルクォートで囲む必要があります。

理由は、JSON内にカンマ(,)が含まれているためです。CSVではカンマがフィールドの区切り文字として使われるので、JSON文字列がダブルクォートで囲まれていないと、CSVパーサーが途中でフィールドが区切られていると勘違いしてしまいます。

例えば、{"name":"田中","age":30}というJSON文字列をそのままCSVに書くと、CSVパーサーは最初のカンマを見つけた瞬間に「ここでフィールドが区切られた」と判断してしまい、JSON文字列がバラバラに分割されてしまいます。

そのため、"{"name":"田中","age":30}"のようにJSON文字列全体をダブルクォートで囲みます。

3.2 JSON内のダブルクォートを二重化する

JSON文字列全体をダブルクォートで囲んだら、次にJSON文字列内の全てのダブルクォートを二重化します。

JSONでは、キーや文字列値の前後にダブルクォートが使われています。これらを全て""に置き換える必要があります。

例えば、{"name":"田中","age":30}というJSONをCSVに変換する場合、以下のようになります:

id,json_data
1,"{""name"":""田中"",""age"":30}"
JavaScript

JSON内の全てのダブルクォート(")が、""に置き換わっているのが分かりますね。

複雑なJSONの変換例

配列やネストしたオブジェクトを含む複雑なJSONでも、基本的なルールは変わりません。

全体をダブルクォートで囲んで、内部のダブルクォートを全て二重化するだけです。

id,user_data,tags
1,"{""name"":""佐藤"",""email"":""sato@example.com""}","[""tag1"",""tag2""]"
2,"{""name"":""田中"",""address"":{""city"":""東京"",""zip"":""100-0001""}}","[""premium"",""vip""]"
JavaScript

配列内のダブルクォートも、オブジェクト内のネストしたダブルクォートも、全て同じように二重化されています。

よくある間違いと正しい記述例

よくある間違いを3つ紹介します:

# 間違い1JSON文字列が囲まれていない
1,{"name":"田中","age":30}

# 間違い2JSONのエスケープ方法バックスラッシュを使っている
1,"{\"name\":\"田中\",\"age\":30}"

# 間違い3改行文字がそのまま残っている
1,"{""name"":""田中"",
""age"":30}"

# 正しい記
1,"{""name"":""田中"",""age"":30}"
JavaScript

間違い1と2は、セクション3で説明した通り、JSON文字列全体をダブルクォートで囲み、内部のダブルクォートを二重化する必要があります。

間違い3の改行文字については、JSON内に改行文字(\n)やタブ文字(\t)が含まれている場合、そのままCSVに書き込むとエラーになるため、削除するか、\\n\\tといったエスケープシーケンスに置換する必要があります。

まとめ:CSVダブルクォートエスケープのチェックポイント

CSVファイル中でのダブルクォーテーションのエスケープでお困りの皆さんのために、最後にチェックポイントをまとめておきますね!

  1. フィールド内のダブルクォートは二重化("")する
    • CSV標準(RFC4180)に従って、""で表現する
    • JSONのエスケープ方法(\")は使えない
  2. カンマや改行を含むフィールドは全体をダブルクォートで囲む
    • JSON文字列をCSVに変換する場合は必須
    • 囲んだ後、内部のダブルクォートは全て二重化する
  3. 改行・タブ文字を事前に処理する
    • 改行文字が含まれている場合は削除またはエスケープする

この3つのポイントを押さえておけば、CSVでのダブルクォーテーションエスケープで悩むことはかなり減ると思います。同じような問題で困っている方の参考になれば嬉しいです!

-プログラミング