LoginSignup
3
1

More than 1 year has passed since last update.

pythonで書いたlambdaのreturnはjson.dumps()されている

Last updated at Posted at 2022-06-25

はじめに

もうタイトルがそのまんま結論なんですけど、
色々読んで試してやっと自分の中で解決したので記事にします。

対象読者は

  • 公式ディベロッパーズガイドを読んでもあまりピンと来なかった方
  • lambdaからの返り値に無駄にバックスラッシュついてて困ってる方

です。

結論

pythonで書いたlambdaのreturnはjson.dumps()されています。
なので一度json.dumps()したものを要素として渡すと
意図しないバックスラッシュがついてきます。

公式のディベロッパーズガイドの「値の返し(Returning a value)」のところ読むと書いてあるんですが、
最初は日本語版読んでも意味わかんなくて
英語で読んでやっとあれ?となって
いろいろ試してやっと「そういうことか!」となりました。

公式のディベロッパーズガイドはこちら
日本語版:https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/python-handler.html#python-handler-return
英語版:https://docs.aws.amazon.com/lambda/latest/dg/python-handler.html#python-handler-return

何で困った?

お試しでCloudFlont+S3+API Gateway+Lambda使ったアプリを作ってみていたところ
(他にもいっぱいトラブったので今度記事にしたい)
最終的にフロントエンドに返ってきた値がどうもうまく取得できてないぞとなったことがきっかけでした。
(fetch使ってPOSTした後にresponseのbodyをresponse.json()→data.keyで取得しようとしたところ、data.keyの値がundefinedになっていた)

その時書いてたLambda関数は
いろんな処理すっ飛ばして簡単にすると以下のような感じでした。

import json

def lambda_handler(event, context):
    result = "hogehoge"
    dict = {"result":result}
    json_data = json.dumps(dict)
        
    return {
        'statusCode': 200,
        'body':json_data
    }

そんでもってTestしてみると返ってきたResponseはこんな感じ

Response
{
  "statusCode": 200,
  "body": "{\"result\": \"hogehoge\"}"
}

"""
ほんとは以下のように出力してほしい
Response
{
  "statusCode": 200,
  "body": "{"result": "hogehoge"}"
}
"""

めっちゃいらんバックスラッシュついとる...
そりゃkey読めませんわ...

このExamplesを見ながら書いていたので
bodyはjson形式にした値を入れなきゃなんだなあと勝手に思っていたのですが違っていました。

試してみた

公式のディベロッパーズガイドからなんとなくreturnそのものがjson.dumps()されているのではないか
ということを察したので、いくつか試してみることにしました。

その1:json.dumps()したものをjson.dumps()するとどうなる?

察したことが正しいか試すためにまずjson.dumps()したものをjson.dumps()してみました

dict = {"result":"hogehoge"}
json_dumps_1 = json.dumps(dict)
json_dumps_2 = json.dumps(json_dumps_1)
print(json_dumps_1) #print結果→ {"result": "hogehoge"}
print(json_dumps_2) #print結果→ "{\"result\": \"hogehoge\"}"

json_dumps_2の結果が先のresponseのbodyのvalueと同じような形になっています。
json形式にするためにはダブルクオーテーションのまえにはバックスラッシュがつくので、そのせいですね。

その2:returnを前もってjson.dumps()しておくとどうなる?

lambda関数のreturnに渡すものを前もってjson.dumps()してみます。

import json

def lambda_handler(event, context):
    result = "hogehoge" # 仮にhogehogeとしとく
    dict = {"result":result}
    
    return_obj ={
        'statusCode': 200,
        'body':dict
    }
    
    return_obj_json = json.dumps(return_obj)
    print(return_obj_json) # {"statusCode": 200, "body": {"result": "hogehoge"}}
    
    return return_obj_json

このときのresponseは以下の通りです

Response
"{\"statusCode\": 200, \"body\": {\"result\": \"hogehoge\"}}"

responseがjson.dumps()したものをjson.dumps()した形になっていますね。

意図した出力を得るためには

ということで意図した出力を得るためにはdictをそのまま渡してあげればよかったです。

import json

def lambda_handler(event, context):
    result = "hogehoge"
    dict = {"result":result}
    
    return {
        'statusCode': 200,
        'body':dict
    }

この時のresponseは以下です

Response
{
  "statusCode": 200,
  "body": {
    "result": "hogehoge"
  }
}

うまくいきました!

おわりに

公式の日本語をちゃんと理解できなかったばっかりに
だいぶ悩んだのですが
JSONなんたるや(誤解してた)から復習できて
とてもいい機会になりました。

その他参考

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1