階層化されたデータをHTTPのGETリクエストのパラメータに含める方法。

・・・が知りたい。
POSTのリクエストボディのシリアライズの方法はかなり柔軟なんですが、GETはURLにクエリパラメータとして添えるしかないので、柔軟性が低いです。

URLエンコードして渡す。

たとえばですが、四則演算があったとして、これをHTTPリクエスト経由で答えを求めたいとします。

(1 + 2) * 3

この計算式をURLエンコードして渡すというのがひとつです。

/api/calculate?query=%281%20%2B%202%29%20%2A%203

オブジェクトは渡しにくい

あまり例えがよくないかもしれないですが、この計算式は階層構造をもっていて、JavaScriptのオブジェクトで表現すると以下のように表現できなくもないです。

var query = {
	operator : 'multiply',
	values : [{
		operator : 'plus',
		values : [1, 2]
	}, 3]
};

これをGETリクエストで送りたいのですが、リクエストの美しさとサーバでの処理のしやすさを考えると、なかなか良い方法がありません。

$.ajax({
	url : '/api/calculate',
	type : 'GET',
	data : {
		query : query
	}
});

jQueryだと、配列の類は、カッコつきのキー名に変換されて送信されます。

/api/calculate?query%5Boperator%5D=multiply&query%5Bvalues%5D%5B0%5D%5Boperator%5D=plus&query%5Bvalues%5D%5B0%5D%5Bvalues%5D%5B%5D=1&query%5Bvalues%5D%5B0%5D%5Bvalues%5D%5B%5D=2&query%5Bvalues%5D%5B%5D=3

読みにくいのでデコードしたものも載せます。

/api/calculate?query[operator]=multiply&query[values][0][operator]=plus&query[values][0][values][]=1&query[values][0][values][]=2&query[values][]=3

PHPなどだと、この形式で親子関係を保ったまま$_GET変数に入ってくれるので、この形式が一般的なのかもしれません。

JSON化してからURLエンコードする

もう少しだけまともな状態でリクエストパラメータに含めようと思うと、JSON化してからURLエンコードして送信するという手があります。

$.ajax({
	url : '/api/calculate',
	type : 'GET',
	data : {
		query : JSON.stringify(query)
	}
});

こうすると、次のようなリクエストになります。

/api/calculate?query=%7B%22operator%22%3A%22multiply%22%2C%22values%22%3A%5B%7B%22operator%22%3A%22plus%22%2C%22values%22%3A%5B1%2C2%5D%7D%2C3%5D%7D

デコードしたものも載せます。

/api/calculate?query={"operator":"multiply","values":[{"operator":"plus","values":[1,2]},3]}

JSONなのでnullやbooleanが文字列化されず区別できるというメリットがあり、少しだけコンパクトにまとまります。GETリクエストのURLは、ブラウザによって最大長があるので、短いに越したことはないと思います。
しかしながら、このJSON化されたパラメータをパースするような仕様のサーバサイドフレームワークは、さすがに見たことがないので、あまり一般的ではないのかもしれません。

POSTはボディにオブジェクトを投げ込める

ここまでGETリクエストの話をしていましたが、POSTリクエストでは、ボディにオブジェクトを含められるので、こういう悩みはあまりありません。

$.ajax({
	url : '/api/calculate',
	type : 'POST',
	contentType:'application/json',
	data : JSON.stringify(query)
});

だから、あきらめてPOSTを使うという手もあります・・・。
何か良い方法をご存知の方いたら教えて下さい。そもそもそんな巨大なパラメータがGETリクエストで必要な状況はあまりないのでしょうが・・・。

コメント

タイトルとURLをコピーしました