Help us understand the problem. What is going on with this article?

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

More than 5 years have passed since last update.

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オプション付きでシリアライズ

長いので該当箇所だけ。

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした