👻

API GatewayとData Firehoseの統合で遭遇したJSON変換問題とその解決策

2024/05/10に公開1

導入部

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

AsahiAsahi

こちらの記事に救われました。ありがとうございます