Node.jsでnative2asciiとJSON.stringifyする際は順番に気をつけよう

前提

文字列を安全に送る、特にクライアントサイドのJavaScriptに送るにはしばしばUnicodeのエスケープシーケンスが使われることがあります。(セキュリティ検証標準であるOWASPがUnicodeは全て文字参照に変換することを推奨していたりする)

ところが、JavascriptにはJDKのnative2asciiのようなものは用意されていません。が、npmに native2ascii というまんまのものがあります。

ところがこいつがちょっと厄介で、実装が以下のようになっていいます。

node_modules/native2ascii.js
// 略

exports.native2ascii = native2ascii;
exports.ascii2native = ascii2native;

なんと native2ascii という名前でありながら ascii2native も exports している。
(JAVAの native2ascii の場合は -reverse オプションを使用するようになっている)

なので当然使い方は、

const native2ascii = require('native2ascii');
console.log(native2ascii.native2ascii('あ'));

のようになってしまう。。。とても気持ち悪い。どういう名前の変数に入れたら気持ちよくなるんでしょうか。。。

本題

ところでこの native2ascii というか \ が含まれている文字列を JSON.stringify 通すのに順番を間違えると予想打にしない結果になります。

const native2ascii = require('native2ascii');
let json1 = {
    a: native2ascii.native2ascii('あ'),
    b: native2ascii.native2ascii('い'),
    c: native2ascii.native2ascii('う')
}
let json2 = {
    a: 'あ',
    b: 'い',
    c: 'う'
}
console.log(JSON.stringify(json1));
// {"a":"\\u3042","b":"\\u3044","c":"\\u3046"}
console.log(native2ascii.native2ascii(JSON.stringify(json2)));
// {"a":"\u3042","b":"\u3044","c":"\u3046"}

native2ascii を先に通すと\をさらに\で2重にエスケープする現象が起きてしまいます。なので native2ascii は後で通す必要があります。

どうやら JSON.stringify に\をさらにエスケープするような処理が入っていそうです。(v8の実装を実際に読んでないので真意の程はわかりません。。。)

Node.js からJsonでUnicodeのエスケープシーケンスを送る場合は順番に気をつけましょう。

現場からは以上です。:innocent:

Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account log in.