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 的人都可以这样做。
我正在使用 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 的人都可以这样做。