LoginSignup
3
5

More than 5 years have passed since last update.

同名のフィールドを複数含むリクエストをjQuery.ajaxで投げれなかった話と泥臭い解決法

Last updated at Posted at 2015-02-14

Google Closure CompilerのREST APIを呼ぶコードをPythonからJSに書き直した時にハマったので備忘録

元コード(Python)

元々動いていたソースでは、こんな感じでリクエスト作って投げていた。
jsCodeには、すでにコンパイル対象のJavascript文字列が入っているものとする。

params = urllib.urlencode([
        ('js_code',jsCode),
        ('compilation_level', 'SIMPLE_OPTIMIZATIONS'),
        ('output_format', 'json'),
        ('output_info', 'compiled_code'),
        ('output_info', 'warnings'),
        ('output_info', 'errors'),
        ])

headers = { "Content-type": "application/x-www-form-urlencoded" }
conn = httplib.HTTPConnection('closure-compiler.appspot.com')
conn.request('POST', '/compile', params, headers)
response = conn.getresponse()
data = response.read()
conn.close()

ここで、"output_info"パラメータが3つあるが、リクエストではこんな感じになる。

Developer_Tools_-_file____Users_Takuro_git_kiiServerTool_index_html.png

移植先コード - ダメな例(JavaScript)

JSにさっくりと書き直したもの。ブラウザで走らせるのでjQueryを使っている。
(node.jsのhttpで書いてもほぼ同じことになると思うが。)

var params = {
    "js_code" : jsCode,
    "compilation_level": "SIMPLE_OPTIMIZATIONS",
    "output_format": "json",
    "output_info": ["compiled_code", "warnings", "errors"]
};
$.ajax({
    url : "http://closure-compiler.appspot.com/compile",
    type : "POST",
    contentType : "application/x-www-form-urlencoded",
    data : params,
    dataType : "json"
}).done(function(res){...}).fail(function(e){...});

これは、こんな感じでoutput_infoが配列になる。selectとかでよくあるパターンだけど、Closure Compiler様はデリケートなので、これはエラーになる。
具体的には"ServerError"が返ってきて、「"output_info[]"なんてパラメータは知らん。出直せ」と言われる。

Developer_Tools_-_file____Users_Takuro_git_kiiServerTool_index_html.png

移植先コード - 泥臭く直した例(JavaScript)

公式ドキュメント見たりいろいろ探したけどクリティカルな解決策が見つからなかったので、とりあえず基本に立ち返って、自分でシリアライズする。

var params = [
    { key : "js_code",           val : jsCode },
    { key : "compilation_level", val : "SIMPLE_OPTIMIZATIONS" },
    { key : "output_format",     val : "json" },
    { key : "output_info",       val : "compiled_code" },
    { key : "output_info",       val : "warnings" },
    { key : "output_info",       val : "errors" }
];
paramStr = $.map(params, function(n){
    return encodeURIComponent(n.key) + "=" + encodeURIComponent( n.val )
}).join("&").replace(/%20/g, "+");

$.ajax({
    url : "http://closure-compiler.appspot.com/compile",
    type : "POST",
    contentType : "application/x-www-form-urlencoded",
    data : paramStr,
    processData : false,
    dataType : "json"
}).done(function(res){...}).fail(function(e){...});

泥臭いけど、これは動く。

Developer_Tools_-_file____Users_Takuro_git_kiiServerTool_index_html.png

とりあえずめでたし。
でも、すっきりしないー。

(2/20追記) 正解

smzkさんから情報いただきました。1.4から追加になった traditional オプションを有効にすると、シリアライズ時の深い整形処理をやらずに、古い形式で出してくれるようだ。

var params = [
    { key : "js_code",           val : jsCode },
    { key : "compilation_level", val : "SIMPLE_OPTIMIZATIONS" },
    { key : "output_format",     val : "json" },
    { key : "output_info",       val : "compiled_code" },
    { key : "output_info",       val : "warnings" },
    { key : "output_info",       val : "errors" }
];
paramStr = $.param(params, true);//traditionalオプション付きでシリアライズ

長いので該当箇所だけ。

いや、すっきりしました。

3
5
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
5