AWS API 网关数据戳不可 JSON 序列化

AWS API gateway Datestamp is not JSON serializable

我正在使用 lambda 函数并使用 API 网关 rest api 触发它。测试时出现以下错误。我需要在请求正文中传递 Datestamp 作为输入

我用谷歌搜索并找到了这个 link 并尝试了这个解决方案,但它没有用 - https://code-maven.com/serialize-datetime-object-as-json-in-python

我的index.py-

dynamodb = boto3.resource('dynamodb')
resultstablename=('%s-%s-results' % (Project, Environment))
resultstable = dynamodb.Table(resultstablename)


def lambda_handler(event, context):
    try:
        result = []
        queryresponse = resultstable.scan()
        for i in queryresponse['Items']:
            result.append(i['reports'])

        block=['{"type": "section","text": {"type": "mrkdwn","text": "*Found below reports using Datestamp provided*"}}']
        for item in result:
            print(item)
            print(event['Datestamp'])
            if item.find(event['Datestamp']) != -1:
                itema='{"type": "section","text": {"type": "mrkdwn","text": "<https://%s/%s/%s/index.html|%s>"}}' % (SiteSpeedURL,SiteSpeedPreFix,item,item)
                block.append(itema)

block=('[{}]'.format(', '.join(block)))
        
        url = "%s" % (SlackURL)           
        msg = {
        "channel": "%s" % (ChannelName),
        "username": "%s" % (Username),
        "icon_emoji": ":robot_face:",
        "blocks": "%s" % (block),
            }
        encoded_msg = json.dumps(msg).encode('utf-8')
        **resp = http.request('POST',url, body=encoded_msg)**
        
        return("200")

当我像这样向聊天机器人发送命令时,相同的代码工作正常 -

lambda invoke --function-name monitoring-chatbot-shashank --payload {“Datestamp”:“2020-12-23"}

但是当我在请求正文中使用从 API 网关调用此函数时,与此相同的有效负载会抛出错误。

使用休息端点使用 API 网关调用时出现错误 -

Wed Jan 06 11:47:05 UTC 2021 : Lambda execution failed with status 200 due to customer function error: Unable to marshal response: KeyError('Datestamp') is not JSON serializable. Lambda request id: 8baea1a2-517a-4f69-8a8f-6f17746dd360
Wed Jan 06 11:47:05 UTC 2021 : Method completed with status: 502

我不知道还能做什么。如果有人对此有任何想法,请告诉我。

这与日期时间本身无关,问题可能出在这里:

if item.find(event[Date2]) != -1

event 字典没有 '2020-12-22' 键,它引发了 KeyError。 API 网关尝试将此回溯消息视为 JSON 响应,并且可以理解地无法将其序列化。

您的问题是您希望 event 成为请求正文,但事实并非如此。而不是您通过 CLI 传递的对象,

event == {"Datestamp": "2020-12-23"}

您实际上会得到一个由 API 网关生成的描述请求的对象(参见 docs),其中包括作为字符串的请求正文。

event == {
    "resource": "/",
    "path": "/",
    "httpMethod": "GET",
    "requestContext": {
        "resourcePath": "/",
        "httpMethod": "GET",
        "path": "/Prod/",
        ...
    },
    "headers": {
        "accept": "text/html",
        ...
    },
    "multiValueHeaders": {
        ...
    },
    "queryStringParameters": null,
    "multiValueQueryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "body": "{\"Datestamp\": \"2020-12-23\"}",
    "isBase64Encoded": false
}

所以要将 JSON 正文作为 Python 字典,试试这个:

body = json.loads(event["body"])

...

if item.find(body['Datestamp']) != -1:
    ...

如前一个答案所示,“不可 JSON 可序列化”位指的是 KeyError"Datestamp" 不在事件中时引发的。如您所见,API 网关会将失败的 Lambda 执行(例如未捕获的异常)视为网关错误和 return 502。这可能没问题,但如果您想 return不同的错误(and/or 记录更多信息),那么将所有代码包装在 try/except 块中会很有帮助。我也经常喜欢在每个函数的开始打印整个事件,以帮助调试 HTTP 位。

def handler(event, context):
    try:
        print(event)  # helps debug input, not for production
        
        # main app code
        ...
    except Exception as e:
        print(repr(e))  # helps debug other issues, not for production

        return {
            "statusCode": 500,
            "body": "Internal server error: " + repr(e),  # DEFINITELY not for production
        }

确保仅在调试时执行此操作 - 当您打印此内容时,任何有权访问您的日志的人都可以获得有关应用程序状态的信息,其中可能包括敏感数据,并且当您将其包含在 HTTP 响应中时 任何有权访问您的 API 的人都可以这样做。