[アップデート] Amazon Connectの「Lambda関数を呼び出す」でパラメーターとレスポンスにJSONが使えるようになったので検証してみた
みなさん、こんにちは!
福岡オフィスの青柳です。
Amazon Connectのコンタクトフローで「AWS Lambda関数を呼び出す」ブロックを使う際に、「入力パラメータ」および「出力レスポンス」それぞれに「JSON形式」が指定できるようになりました。
Amazon Connect launches expanded JSON attribute support in flows
これまでは、Lambda関数に渡す「入力パラメータ」も、Lambda関数から受け取る「出力レスポンス」も、いずれも「キーと値のペア」である必要がありました。
これが「JSON形式」でも指定できるようになったというアップデートです。
なお、今回のアップデートは正確には「AWS Lambda関数を呼び出す」ブロックと「ビューを表示」ブロックがJSONに対応したという内容なのですが、今回は「Lambda関数を呼び出す」ブロックについて使い方などを調査・検証しました。
(今回はLambda関数のランタイムとして「Node.js 18.x」を選択し、言語はJavaScriptを使用しました)
設定する箇所
「AWS Lambda関数を呼び出す」ブロックのプロパティにおいて、「入力パラメータ」の設定には「JSONを設定」、「出力レスポンス」の設定には「JSON」の選択肢がそれぞれ追加されています。
「入力パラメータ」の設定方法とLambda関数での参照方法
固定値を渡す方法
まず、JSONで使用可能な各「データ型」を使って、パラメータを指定してみます。
指定したJSONの内容:
{ "keyNumber": 123, "keyString": "hoge", "keyBoolean": true, "keyNull": null, "keyObject": { "subKey1": "value1", "subKey2": "value2" }, "keyArray": [ "value3", "value4" ] }
指定した入力パラメータは、これまでと同じく「イベントJSON」としてLambda関数へ渡されます。
上記の入力パラメータを指定した際のイベントJSONの内容は、以下のようになりました。
{ "Details": { "ContactData": { : <省略> : }, "Parameters": { "param1": { "keyNumber": 123, "keyString": "hoge", "keyBoolean": true, "keyNull": null, "keyObject": { "subKey1": "value1", "subKey2": "value2" }, "keyArray": [ "value3", "value4" ] } } }, "Name": "ContactFlowEvent" }
JSON内で使用した各データ型「数値型」「文字列型」「Boolean型」「Null型」が問題無くイベントJSONとしてLambda関数に渡っています。
また、JSONのネストされた構造型である「オブジェクト型」や、配列を使ったJSONについても、問題なく認識されています。
渡された入力パラメータをLambda関数のコード内で使用するには、以下のようにすればOKでした。
export const handler = async(event) => { : let value_number = event['Details']['Parameters']['param1']['keyNumber']; let value_string = event['Details']['Parameters']['param1']['keyString']; let value_boolean = event['Details']['Parameters']['param1']['keyBoolean']; let value_null = event['Details']['Parameters']['param1']['keyNull']; let value_object = event['Details']['Parameters']['param1']['keyObject']['subKey1']; let value_array = event['Details']['Parameters']['param1']['keyArray'][0]; :
注意点としては、JSONで渡したデータは、入力パラメータの「宛先キー」として指定したキー (今回の場合は「param1」) の配下にぶら下がるという点です。
(「Parameters」の直下に指定したJSONデータをぶら下げることはできないと思われます)
動的な値を渡す方法
Lambda関数を使って複雑な処理を行うためには、入力パラメータとして固定値のみではなく「コンタクト属性」を使って動的な値を渡す必要があります。
試しに、JSONを以下のように指定してみます。
{ "key1": $.CustomerEndpoint.Address, "key2": $.Attributes.test }
$.CustomerEndpoint.Address
はシステム属性「顧客の電話番号」を、$.Attributes.test
はユーザー定義属性「test」をそれぞれ表します。
(もちろん、ユーザー定義属性「test」は定義済みの前提です)
このように指定したところ、「無効なJSON」と怒られてプロパティを保存することができませんでした。
そこで、以下のようにしてみました。
{ "key1": "$.CustomerEndpoint.Address", "key2": "$.Attributes.test" }
今度は受け付けてくれたようです。
このようにして「コンタクト属性」を使った入力パラメータを指定した場合、イベントJSONの内容は以下のようになりました。
{ "Details": { "ContactData": { : <省略> : }, "Parameters": { "param1": { "key1": "+81XXXXXXXXXX", "key2": "hogehoge" } } }, "Name": "ContactFlowEvent" }
ということで、動的な値を渡すのも問題無く行えるようです。
「出力レスポンス」の設定方法とコンタクトフローでの参照方法
今度は、Lambda関数の戻り値をコンタクトフローから「JSON形式」として参照する方法を検証します。
基本的なデータ型の場合
まずは、基本的なデータ型 (数値型、文字列型、ブール型、Null型) をLambda関数の戻り値として設定してみます。
export const handler = async(event) => { const response = { "keyNumber": 123, "keyString": "hoge", "keyBoolean": true, "keyNull": null }; return response; };
コンタクトフローでLambda関数の戻り値を参照する方法はいくつかあります。
1つ目の方法として、「コンタクト属性の設定」ブロック等でLambda関数の戻り値を「外部」属性として参照する方法を試してみます。
下図のようにして、「外部」属性の値を「ユーザー定義」属性への設定 (代入) します。
「外部」属性から「ユーザー定義」属性へ正しく値が代入できたかどうか、コンタクトフローのログで確認しましょう。
(ログのうち必要な部分のみを抜き出しています)
{ "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueNumber", "Value": "123" } } { "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueString", "Value": "hoge" } } { "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueBoolean", "Value": "" } } { "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueNull", "Value": "" } }
「数値型」「文字列型」は戻り値から正しく値を参照することができましたが、「ブール型」「Null型」は値を正しく参照することができませんでした。(値が設定されていない)
Lambda関数の戻り値を参照する2つ目の方法として、「プロンプトの再生」ブロック等で「$.External」記法を使って「外部」属性の参照を試みます。
テキスト中で以下のように記述することで「外部」属性の各値が参照できるはずです。
$.External.keyNumber
$.External.keyString
$.External.keyBoolean
$.External.keyNull
正しく値を参照できたか、コンタクトフローのログで確認しましょう。
{ "ContactFlowModuleType": "PlayPrompt", "Parameters": { "TextToSpeechType": "text", "SpeakingStyle": "None", "Text": "1番目の値は 123 です。\n2番目の値は hoge です。\n3番目の値は です。\n4番目の値は です。", "Voice": "Kazuha", "GlobalEngine": "Neural" } }
「数値型」「文字列型」の各値は正しく参照できました。
しかし、「ブール型」「Null型」は値を正しく参照することができませんでした。
(実際のプロンプト再生でも、「123」「hoge」は再生され、「true」「null」の部分は何も再生されないことが確認できると思います)
このように2つの方法を試しましたが、いずれの方法でも「ブール型」「Null型」の値は参照できないという結果になりました。
まあ、コンタクト属性には「データ型」の概念が無くブール型やNull型をそのまま扱うのは難しいと思いますので、これらのデータ型がLambda関数から受け取れないことはあまり問題にならないでしょう。
Lambda関数のコードを記述する際の注意点として、ブール型やNull型をそのまま戻り値に設定せず、文字列型にキャストするか、戻り値を文字列として返す (「"enable"」「"disable"」など) ことをお勧めします。
「オブジェクト型」の場合
今度は、「オブジェクト型」をデータ構造に持つJSONを戻り値に設定してみます。
export const handler = async(event) => { const response = { "keyObject": { "subKey1": "value1", "subKey2": "value2" } }; return response; };
「コンタクト属性の設定」ブロック等でLambda関数の戻り値を「外部」属性として参照するには、属性の名前をkeyObject.subkey1
のように「キー名+"."+サブキー名」の形式で指定します。
コンタクトフローのログを確認すると、正しく値を参照できていることが分かります。
{ "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueObject1", "Value": "value1" } } { "ContactFlowModuleType": "SetAttributes", "Parameters": { "Key": "valueObject2", "Value": "value2" } }
「プロンプトの再生」ブロック等で「$.External」記法を使って「外部」属性を参照する場合は、$.External.keyObject.subKey1
のように記述します。
こちらも、コンタクトフローのログより、正しく値を参照できていることが確認できます。
{ "ContactFlowModuleType": "PlayPrompt", "Parameters": { "TextToSpeechType": "text", "SpeakingStyle": "None", "Text": "1番目の値は value1 です。\n2番目の値は value2 です。", "Voice": "Kazuha", "GlobalEngine": "Neural" } }
もちろん、実際に「value1」「value2」とプロンプト再生されます。
配列の場合
最後に、配列をデータ構造に持つJSONを戻り値に設定してみます。
export const handler = async(event) => { const response = { "keyArray": [ "value1", "value2" ] }; return response; };
この場合ですが、「コンタクト属性の設定」「プロンプトの再生」の各ブロックで「外部」属性を参照する記述方法をいくつか試しましたが、いずれも値を参照することはできませんでした。
keyArray.0
あるいは$.External.keyArray.0
keyArray.1
あるいは$.External.keyArray.1
keyArray[0]
あるいは$.External.keyArray[0]
keyArray[1]
あるいは$.External.keyArray[1]
他に思いつく方法が無かったので、配列をデータ構造を持つJSON形式の戻り値を参照するのは諦めました。
検証結果
今回の検証結果をまとめると、以下のようになります。
- コンタクトフローからLambda関数に対してパラメーターを与える時
- 一般的なJSONの記法で問題ない
- データ型は「数値型」「文字列型」「ブール型」「Null型」に加えて、オブジェクト型や配列も記述できる
- 「$.」記法を使ってコンタクト属性の値をJSONに含めることも可能
- Lambda関数からの戻り値をコンタクトフローで参照する時
- データ型は「数値型」「文字列型」および「オブジェクト型」であれば参照できる
- 「ブール型」「Null型」および配列は参照できない
戻り値の「配列」については、もしかすると参照する方法があるのかもしれませんが、AWS公式ドキュメントには説明している箇所が見当たらず、現時点では不明です。
おわりに
今回の「What's new」の説明では "For example, you can now build self-service experiences to help customers track their order status based on multiple purchases in the last month rather than the single most recent purchase." (日本語に訳すと「例えば、『最近の1回の購入』ではなく『先月の複数回の購入履歴』から顧客が注文状況を追跡できるように、セルフサービス体験を構築できます」) となっていました。
これを読んで、コンタクトフローから都度Lambda関数を呼び出さなくても構造化された (あるいはリスト化された) データのやり取りを行えるようになることを期待していました。
しかし、検証した限りでは、パラメーターや戻り値でJSON形式を指定できても、上手く活用できる場面は限定的 (ほぼ無い) ではないかと思いました。
理由は、構造化・リスト化されたデータをコンタクトフローで扱う方法が仕組みとして提供されていないためです。
例えば、構造化されたデータの要素にアクセスする際に、サブキーを動的に変数 (コンタクト属性) で与えて指定したり、「for each」 的な処理を行うといったことができません。
Lambda関数が戻り値を「オブジェクト型」を含むJSON形式で返しても、コンタクトフローから参照する際には構造が固定化されたデータとして扱うしかなく、これだとせいぜい「意味的にまとまりのある値をグループ化する」程度の効果しか期待できません。
また、コンタクトフローには「ループ」ブロックが用意されていますが、ループ内で現在の繰り返し回数を取得する手段はありません。
そもそも「配列」を含むJSON形式をコンタクトフローから参照する方法が無い (分からない) ので議論する余地も無いのですが、仮に可能だったとしても「配列として返されたデータを1件ずつ取り出して読み上げる」等の処理を行うことはできないのではないかと思います。
結論としては、現時点ではLambda関数の「入力パラメーター」と「出力レスポンス」をJSON形式でやり取りする必要性は薄いと考えますが、将来的にコンタクトフローの仕組みを含めて機能が拡張されることを期待したいと思います。