Boto3でLambdaを呼び出すと”Unable to marshal response: Object of type StreamingBody is not JSON serializable”エラーとなる
こんにちは、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\"}]"
おわりに
あまり使ったことがないメソッドやデータを扱うときは、今回のようにまずデータの型を調査する癖をつけたいですね。
以上