この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部の若槻です。
今回は、Boto3でLambdaを呼び出した時の戻り値の処理がUnable to marshal response: Object of type StreamingBody is not JSON serializable
エラーとなったので対処した話です。
事象
以下のように実行される側(scan_func
)と実行する側(execute_func
)のLambdaがあり、後者から前者を呼び出してscan_func
からの戻り値を得たいです。
- 実行される側(
scan_func
)
import json
import boto3
def lambda_handler(event, context):
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('wakatsuki_test')
resp = table.scan()
return json.dumps(resp['Items'])
- 実行する側(
invoke_func
)
import json
import boto3
def lambda_handler(event, context):
resp = boto3.client('lambda').invoke(
FunctionName='scan_func',
InvocationType='RequestResponse'
)
return resp
しかしinvoke_func
を実行したところ、下記のUnable to marshal response: Object of type StreamingBody is not JSON serializable
エラーが発生してしまいます。
Response:
{
"errorMessage": "Unable to marshal response: Object of type StreamingBody is not JSON serializable",
"errorType": "Runtime.MarshalError"
}
調査
Boto3のドキュメントを確認してみます。
ドキュメントによると、boto3.client('lambda').invoke()
のレスポンスは以下のような形式を取るとのことです。
{
'StatusCode': 123,
'FunctionError': 'string',
'LogResult': 'string',
'Payload': StreamingBody(),
'ExecutedVersion': 'string'
}
このうち、関数からのレスポンスはPayload (StreamingBody)
に含まれるとのことです。今回エラーとなっているのはこの部分のJSONシリアライズです。
・ Payload (StreamingBody) -- The response from the function, or an error object.
ではこのStreamingBody
はどんなデータ型であるかというと、botocoreのドキュメントに記載がありました。
class botocore.response.StreamingBody(
raw_stream, content_length
)Wrapper class for an http response body.
どうやらread()
メソッドを使えばStreamingBodyに含まれるレスポンスボディを取得できそうです。
read(amt=None)
Read at most amt bytes from the stream. If the amt argument is omitted, read all data.
解決
調査を踏まえて、Lambdaを呼び出したレスポンスをresp['Payload'].read()
のようにパースすることにより、scan_func
からの戻り値を得ることができるようになりました。
import json
import boto3
def lambda_handler(event, context):
resp = boto3.client('lambda').invoke(
FunctionName='test_wakatsuki',
InvocationType='RequestResponse'
)
return resp['Payload'].read()
Response:
"[{\"id\": \"aaa\"}]"
おわりに
あまり使ったことがないメソッドやデータを扱うときは、今回のようにまずデータの型を調査する癖をつけたいですね。
以上