AWS API Gatewayでapplication/x-www-form-urlencodedの配列パラメータを扱いたい時のマッピングテンプレート
hoge[]を受け取りたい
AWS LambdaとAPI Gatewayを連携させてPOSTを受け取って・・・とやろうとした時に、配列のパラメータの扱いで少しハマりました。
application/x-www-form-urlencodedの単純なkey=valueのPOSTを扱うマッピングテンプレートは、ググればたくさん出てくるんですが、key[]=valueの配列を扱えるものはほとんど出てきませんでした。
唯一まとめてくださっていたのが以下の記事。
こちらの記事のテンプレートをコピペしても動くんですが、リクエスト時のパラメータの状態によって整形後のjsonが不正な形式(浮いたカンマがある)になる場合があったので、自分なりにちょっと改造をしてみました。
テンプレート
{ "headers" : { #foreach( $key in $input.params().header.keySet() ) "$key" : "$input.params().header.get($key)"#if( $foreach.hasNext ),#end #end }, "queryParameters" : { #set( $tmpStr = $input.path('$') ) ##配列をまとめるハッシュと単純な値をまとめるハッシュ #set( $arrayKeyValue = {} ) #set( $simpleKeyValue = {} ) #foreach( $keyAndValueStr in $tmpStr.split( '&' ) ) #set( $keyAndValueArray = $keyAndValueStr.split( '=' ) ) #if( $keyAndValueArray[0].indexOf('[]') > 0) ##「key[]=value」を「key : [value]」に変換してまとめる #set($arraykey = $keyAndValueArray[0].substring(0, $keyAndValueArray[0].indexOf('[]') )) #set($arrayvalue = []) #if($arrayKeyValue.containsKey($arraykey)) #set($arrayvalue = $arrayKeyValue.get($arraykey)) #end #set($dev_null = $arrayvalue.add($keyAndValueArray[1])) #set($dev_null = $arrayKeyValue.put($arraykey, $arrayvalue) ) #elseif( $keyAndValueArray[0].indexOf('%5B%5D') > 0) ##「key[]=value」を「key : [value]」に変換してまとめる(上と全く同じことをやっている) #set($arraykey = $keyAndValueArray[0].substring(0, $keyAndValueArray[0].indexOf('%5B%5D') )) #set($arrayvalue = []) #if($arrayKeyValue.containsKey($arraykey)) #set($arrayvalue = $arrayKeyValue.get($arraykey)) #end #set($dev_null = $arrayvalue.add($keyAndValueArray[1])) #set($dev_null = $arrayKeyValue.put($arraykey, $arrayvalue) ) #else ##単純な「key : value」でまとめる #set($dev_null = $simpleKeyValue.put($keyAndValueArray[0], $keyAndValueArray[1]) ) #end #end ##「key : value」を書き起こす #foreach( $key in $simpleKeyValue.keySet()) "$key" : "$util.urlDecode($simpleKeyValue.get($key))"#if($foreach.hasNext() || $arrayKeyValue.size() > 0),#end #end ##「key : [value]」を書き起こす #foreach( $key in $arrayKeyValue.keySet()) #set( $resultValArr = $arrayKeyValue.get($key) ) "$key" : [#foreach($val in $resultValArr)"$util.urlDecode($val)"#if($foreach.hasNext()),#end#end]#if($foreach.hasNext()),#end #end }, "stage" : "$context.stage", "sourceIp" : "$context.identity.sourceIp", "userAgent" : "$context.identity.userAgent" }
解説とまとめ
単純なkey=valueをまとめるハッシュと、配列のkey[]=valueをまとめるハッシュを別にしました。
最初にパラメータを分解してハッシュに一通りまとめて、最後にいっぺんに文字列として書き起こしていく流れです。
参照元の記事では、配列をハッシュにまとめている間に単純なkey=valueは文字に起こしていたのですが、個人的に「分解→整形」の流れにした方が分かりやすかったので、別々の変数にまとめました。
これでどんなパラメータがきても対応できると思います。
一つ注意といえば、数値も全部文字列にしてしまうので、受け取る側で適宜型変換をしないと行けない点ですね。
application/x-www-form-urlencodedだと結構面倒ごとが多いから大人しくapplication/jsonで送ってもらうのが良いのかもしれません・・・。