XPagesでJavaScriptに文字列を渡すと文字化け… toJson() で解決した理由
XPagesで文字化け? toJson() を使ったらうまくいった話
XPagesでサーバーサイドの文字列をクライアントサイドJavaScriptへ渡す際、
文字列の内容によってはJavaScriptが正しく動作しなくなることがあります。
特に、以下のような文字が含まれている場合は注意が必要です。
- ダブルクォート
" - シングルクォート
' - バックスラッシュ
\ - 改行
- タブ
- 日本語などのUnicode文字
今回、XPagesで文字列をJavaScriptへ渡す処理を見直したところ、
toJson() を使用することで安全に受け渡せることが分かりました。
もともとの処理
例えば、SSJS側に以下のような関数があるとします。
function getSampleText() {
return "商品名:テスト商品";
}
この値をクライアントサイドJavaScriptへ渡したい場合、
単純に以下のように記述したくなります。
#{javascript:getSampleText()}
文字列が単純な内容であれば、問題なく動作する場合もあります。
しかし、実際のデータでは文字列内に改行やダブルクォートなどが含まれることがあります。
例えば以下のような文字列です。
商品名:テスト商品
備考:"特価品"
この文字列をそのままJavaScriptへ埋め込もうとすると、
生成されるJavaScriptが正しい構文にならない可能性があります。
なぜ問題が発生するのか
JavaScriptで文字列を扱う場合、文字列は通常以下のように記述します。
var text = "テスト";
しかし、文字列自体にダブルクォートが含まれていると、
例えば以下のような状態になる可能性があります。
var text = "備考:"特価品"";
これでは、JavaScriptがどこまでを文字列として扱えばよいのか判断できません。
そのため、JavaScriptエラーの原因になります。
また、改行やバックスラッシュなども、
そのままJavaScriptソースへ埋め込むと問題になる場合があります。
つまり、
サーバー側では正常な文字列でも、JavaScriptのソースコードとして直接埋め込むと壊れることがある
ということです。
toJson() を使う
そこで使用できるのがXPagesの toJson() です。
今回の記述は以下です。
#{javascript:toJson(getSampleText())};
getSampleText() が返した文字列を、
toJson() に渡しています。
例えば元の文字列が、
商品名:テスト商品
備考:"特価品"
だった場合、JavaScriptへ渡す際には概念的に以下のような形式になります。
"商品名:テスト商品\n備考:\"特価品\""
ダブルクォートは \"、
改行は \n のように、
JavaScriptやJSONで安全に扱える形式へエスケープされます。
その結果、ブラウザ側では例えば以下のような正常なJavaScriptとして扱うことができます。
var sampleText = "商品名:テスト商品\n備考:\"特価品\"";
JavaScriptが実際に値を取得すると、中身は元通りです。
商品名:テスト商品
備考:"特価品"
処理の流れ
getSampleText()
↓
サーバー側では正常な文字列
商品名:テスト商品
備考:"特価品"
↓
toJson()
"商品名:テスト商品\n備考:\"特価品\""
↓
ブラウザへ出力
↓
JavaScriptが安全に解釈
↓
元の文字列として利用できる
つまり toJson() は、簡単に言うと、
「この文字列をJavaScriptに渡してもぶっ壊れない形にするマン」
と考えると分かりやすいです。
toJson() は文字化けを直す処理ではない
ここは注意が必要です。
toJson() を使用した結果、日本語の表示が正常になり、
「toJson() で文字化けが直った」
ように見える場合があります。
しかし、厳密には toJson() は文字コード変換を行うための関数ではありません。
例えば getSampleText() の時点で、すでに以下のように文字化けしている場合、
繧ケ繝医Μ繝ウ繧ー
以下のようにしても、元の日本語へ復元されるわけではありません。
toJson(getSampleText())
UTF-8やShift_JISなど、文字コードの不一致が原因の場合は、
ファイル読み込み処理やHTTPレスポンスなど、別の箇所を確認する必要があります。
今回うまくいった理由
今回の場合、
getSampleText() で取得した段階では日本語は正常でした。
問題は、その文字列をXPagesからブラウザ側のJavaScriptへ渡す部分にありました。
そこで、
#{javascript:toJson(getSampleText())};
と変更したことで、以下のような処理が行われます。
- JavaScript用の文字列として扱える形になる
- ダブルクォートがエスケープされる
- 改行が
\nのような形に変換される - バックスラッシュなども適切に処理される
- JavaScript側で安全に文字列として解釈できる
その結果、見た目としては
「文字化けが直った」
ように見えた、ということになります。
例えばこんな文字列でも安全になる
例えば以下のようなデータがあるとします。
担当者:"田中"
保存先:C:\work\test
備考:
1行目
2行目
このような文字列をそのままJavaScriptへ渡すのは少し危険です。
toJson() を通すと、概念的には以下のようになります。
"担当者:\"田中\"\n保存先:C:\\work\\test\n備考:\n1行目\n2行目"
これならJavaScriptの文字列として安全に扱うことができます。
まとめ
XPagesのサーバーサイド処理で取得した文字列を、
クライアントサイドJavaScriptへ渡す場合は、
#{javascript:toJson(getSampleText())}
のように toJson() を使用すると安全です。
特に、外部ファイルやDBなどから取得した文字列には、
日本語、改行、ダブルクォート、バックスラッシュなどが含まれることがあります。
そのままJavaScriptへ埋め込むよりも、
toJson() を通したほうが安全に扱えます。
ただし、toJson() は文字化けを修復する関数ではありません。
役割としては、
サーバー側の文字列を、JavaScript側で安全に解釈できるJSON形式の文字列へ変換する
という理解が分かりやすいと思います。
XPagesで
「サーバー側では正常なのにJavaScriptへ渡すとうまく表示されない」
「クォートや改行が入るとJavaScriptエラーになる」
といった場合には、toJson() を試してみる価値があります。



