JSON文字列のエスケープは手書き置換で組まない:JSON.stringifyに任せる理由を手を動かして確かめる
APIのリクエストボディやログを組み立てるとき、任意のテキストをJSON文字列の値として埋め込む場面は多い。このとき「ダブルクォートを \" に、改行を \n に置換すればいい」と手書きの replace を並べると、制御文字やサロゲートペアで簡単に壊れる。結論から言うと、自前で組まず JSON.stringify に任せるのが正解だ。手を動かして確かめる。
手書き置換が漏らすもの
素朴にやるとこうなりがちだ。
1 | |
だが JSON の仕様では、\n \t 以外の制御文字(U+0000〜U+001F)もすべてエスケープが必要だ。例えばバックスペース(U+0008)、フォームフィード(U+000C)、垂直タブ(U+000B)、キャリッジリターンなどが生テキストに混ざると、上の関数はそれらを素通しし、できあがった文字列は不正なJSONになる。
1 | |
JSON.stringify に任せる
JSON.stringify は仕様どおり全制御文字をエスケープし、サロゲートペア(絵文字など)も正しく扱う。返り値は前後にダブルクォートが付くので、値部分だけ欲しいときは両端を1文字ずつ削る。
1 | |
制御文字がきちんとエスケープされ、JSON.parse で完全に元へ戻る。絵文字(サロゲートペア)も壊れない。
非ASCIIを uXXXX にしたい場合
ASCIIしか通らない古い経路へ渡すなら、エスケープ後にさらに非ASCIIを \uXXXX へ変換する。ここはコードポイント範囲で機械的に置換すればよい。
1 | |
まとめ
JSON文字列のエスケープは、\" や \n だけを見て手書きの置換を並べると、バックスペースやフォームフィード・NULなどの制御文字やサロゲートペアで壊れる。JSON.stringify(s).slice(1, -1) に任せれば仕様どおり正しくエスケープでき、JSON.parse で往復も保証される。ブラウザ上で試せる形は JSON文字列エスケープ/アンエスケープ に置いた(処理はすべてブラウザ内で完結する)。