URIエンコードとデコード
JavaScript→Rubyに渡す文字列のエンコードではまったのでメモ。
JavaScriptでURIエンコード
JavaScriptには、文字列をURIエンコードする関数が3つあり、それぞれ動作が違います。
- escape()
- 最初のJavaScriptの仕様で用意されていた関数。
- 完全なURIエンコードではない。またブラウザによって動作が違ったりするらしい。
- encodeURI()
- ECMA-262 3rd Editionで追加された関数。旧ブラウザでは未実装なので注意。
- アルファベット, 10進数字, -_.!~*'()# をエスケープする。
- encodeURIComponent()
- こちらもECMA-262 3rd Editionで追加された関数。
- encodeURI()のエスケープ対象に加えて、,/?:@&=+$もエスケープする。
確認のため、エンコード結果を表示する表を作成してみました。
var stdout = document.getElementById("stdout"); // 変換する文字列 var str = "abcABC日本語 -+=*@.,/?&:;$'\"#_()[]<>!|^~*\\"; // エンコード関数 var list = { escape: function( str ) { return escape(str) }, encodeURI: function( str ) { return encodeURI(str) }, encodeURIComponent: function( str ) { return encodeURIComponent(str) } } // 表を生成する。 var table = "<table border='1px'><tr><th>変換前の文字</th>"; for ( var f in list ) { table += "<th>" + f + "</th>"; } table += "</tr>" for ( var i = 0; i < str.length; i++ ) { table += "<tr>"; var c = str.charAt(i); table += "<td>" + c +"</td>"; for ( var f in list ) { table += "<td>" + list[f](c) + "</td>"; } table += "</tr>"; } stdout.innerHTML = table + "</table>";
確認はこちらから。IE6とFirefox2ではescape()も同じ動作をしました。
Rubyでのデコード
RubyでURIエンコードされた文字列をデコードするには、CGI#unescape()を利用します。
これを使って、JavaScriptでURIエンコードした文字列をデコードしてみます。
require 'yaml' require 'kconv' require 'cgi' # 左から、元の文字列、escape(), encodeURI(), encodeURIComponent() data = [ ["a", "a", "a", "a"], ["b", "b", "b", "b"], ["c", "c", "c", "c"], ["A", "A", "A", "A"], ["B", "B", "B", "B"], ["C", "C", "C", "C"], ["日", "%u65E5", "%E6%97%A5", "%E6%97%A5"], ["本", "%u672C", "%E6%9C%AC", "%E6%9C%AC"], ["語", "%u8A9E", "%E8%AA%9E", "%E8%AA%9E"], [" ", "%20", "%20", "%20"], ["-", "-", "-", "-"], ["+", "+", "+", "%2B"], ["=", "%3D", "=", "%3D"], ["*", "*", "*", "*"], ["@", "@", "@", "%40"], [".", ".", ".", "."], [",", "%2C", ",", "%2C"], ["/", "/", "/", "%2F"], ["?", "%3F", "?", "%3F"], ["&", "%26", "&", "%26"], [":", "%3A", ":", "%3A"], [";", "%3B", ";", "%3B"], ["$", "%24", "$", "%24"], ["'", "%27", "'", "'"], ["\"", "%22", "%22", "%22"], ["#", "%23", "#", "%23"], ["_", "_", "_", "_"], ["(", "%28", "(", "("], [")", "%29", ")", ")"], ["[", "%5B", "%5B", "%5B"], ["]", "%5D", "%5D", "%5D"], ["<", "%3C", "%3C", "%3C"], [">", "%3E", "%3E", "%3E"], ["!", "%21", "!", "!"], ["|", "%7C", "%7C", "%7C"], ["^", "%5E", "%5E", "%5E"], ["~", "%7E", "~", "~"], ["*", "*", "*", "*"], ["\\", "%5C", "%5C", "%5C"], ] data.each{|v| print v[0].tosjis + " " v[1..3].each { |c| print CGI.unescape(c).tosjis + " " } print "\n" }
実行結果です。
- escape()した文字列の場合、日本語と+記号が復元できていません。
- encodeURI()した文字列の場合、+記号が復元できていません。
- ★encodeURIComponent()した文字列は正しくデコードできています。
a a a a b b b b c c c c A A A A B B B B C C C C 日 %u65E5 日 日 本 %u672C 本 本 語 %u8A9E 語 語 - - - - + + = = = = * * * * @ @ @ @ . . . . , , , , / / / / ? ? ? ? & & & & : : : : ; ; ; ; $ $ $ $ ' ' ' ' " " " " # # # # _ _ _ _ ( ( ( ( ) ) ) ) [ [ [ [ ] ] ] ] < < < < > > > > ! ! ! ! | | | | ^ ^ ^ ^ ~ ~ ~ ~ * * * * \ \ \ \