API GatewayとData Firehoseの統合で遭遇したJSON変換問題とその解決策
導入部
AWSのAPI Gatewayを使用してData Firehoseにデータを送信する際、予期せぬ挙動に直面しました。特に、$util.toJson($elem)
を用いた際にデータが正しく読み込まれず、結果としてBase64エンコードされたデータが空になるという問題が発生しました。その問題の原因と、実際に行った解決策について詳細に解説します。
問題の詳細
API GatewayでJSON配列の中のオブジェクトをそのままData Firehoseへ送信するためのマッピングテンプレートを設定していたところ、$util.toJson($elem)
を使用してJSONオブジェクトを文字列化しようとすると、理由は不明ですがデータが空になりました(使い方が間違っている?)。これにより、正しくエンコードされるべきデータが存在せず、Firehoseに空のレコードが送信されてしまうという問題が発生していました(本来ならきちんと構造化してしているべきなのでしょうけど・・・)。
解決策の発見と実装
この問題に対処するために、さまざまな方法を試した結果、$input.json("$[$foreach.index]")
を使用して配列の各要素を直接参照する方法でうまくデータを読み込むことができました。このアプローチでは、VTLの$foreach.index
を利用して、配列内の現在の要素のインデックスを指定し、それを使って$input.json
で直接その要素をJSON文字列として取得します。
実装例
以下のマッピングテンプレートでは、API Gatewayが受信したJSON配列の中のオブジェクトを読み込み、それをBase64エンコードしてFirehoseに送信する方法を示します。
#set($statuses = $input.path('$'))
#set($type = $statuses.getClass().getName())
{
"DeliveryStreamName": "example-delivery-stream",
"Records": [
#foreach($elem in $statuses)
{
#set($json = $input.json("$[$foreach.index]"))
"Data":"$util.base64Encode($json)"
}
#if($foreach.hasNext),#end
#end
]
}
このテンプレートでは、配列の各要素に対して$input.json
を使用してデータを取得し、その結果をBase64でエンコードしています。これにより、元の問題を解決し、データが正しくFirehoseに送信されるようになりました。
結論
よくわからん(ちゃんと勉強すべきなのだろうけど、そんなにVTL触るような実装ないし・・・)
こうしたら良いよって内容が欲しい・・・
Discussion