AWS Lambda 错误:当 url 参数包含 JSON 数组时,“无法将请求正文解析为 json”

Posted

技术标签:

【中文标题】AWS Lambda 错误:当 url 参数包含 JSON 数组时,“无法将请求正文解析为 json”【英文标题】:AWS Lambda Error : 'Could not parse request body into json ' when url parameter contains JSON array 【发布时间】:2017-01-10 11:42:49 【问题描述】:

我正在尝试通过传递如下参数来调用我的 Lambda 函数。它包含 撇号(')

https://invoke_url?param=[["kurlo jack's book","Adventure Books",8.8,1]]

字符串化为'https://invoke_url?param=%5B%5B%229780786706211%22s....`

我使用下面的映射将参数传递给 lambda

  "query": 
    #foreach($queryParam in $input.params().querystring.keySet())
    "$queryParam": "$util.escapejavascript($input.params().querystring.get($queryParam))" #if($foreach.hasNext),#end

    #end
    

我收到以下错误

"message": "Could not parse request body into json: Unrecognized character escape \'\'\' (code 39)\n at [Source: [B@5b70c341; line: 29, column: 65]"  

从映射模板中删除双引号后,我也尝试过。但是没用。

【问题讨论】:

你能在字符串被解析之前打印它吗? @johni 有没有办法在 api 网关集成请求映射上做到这一点? 应该有。我不是 Api Gayeway 专家,但从我过去几天研究的材料来看,似乎对此有支持。无论如何,我认为您的问题与您要解析的字符串有关。没有别的,这根本与 AWS 无关(IMO) 这应该可以回答您关于 Api Gateway ***.com/q/31329958/3454745 的问题 我们是否必须将字符串解码回 API Gateway 的 json 模板部分?还是它在内部解决这个问题? 【参考方案1】:

“查询字符串”(超链接中? 之后的部分)必须是string。无论您构造什么,都必须附加到它上面:https://invoke_url?a=x&b=y

在您的 Lambda 代码中放置:

if( event.hasOwnProperty( 'params' ) )
    if( event.params.hasOwnProperty( 'querystring' ) )
        params = event.params.querystring;

(显然是一些无关的检查,可能没有必要,但是呃)

在您的 API 网关中转到:

APIs -> api_name -> Resources -> invoke_url -> GET -> Method Execution

在 URL 查询字符串参数下“添加查询字符串”ab(或其他)

当您点击www.com/invoke_url?a=x&b=y 时,您现在可以通过以下方式访问它们:

...
params = event.params.querystring;
console.log( params.a, params.b );
...

【讨论】:

实际上我正在发送这样的参数:invok_url?param=%5B%5B%229780786706211%22%2C%22Endurance%3A%20Shackleton%27s%20Incredible%20Voyage%22%2C%22Adventure%20Books %22%2C8.8%2C1%5D%5D【参考方案2】:

我没有解决方案,但我已经缩小了根本原因。 Lambda 似乎不喜欢用单斜杠转义单引号。

如果您将映射模板硬编码为如下所示:


    "query-fixed": 
        "param": "[[\"kurlo jack\\'s book\",\"Adventure Books\",8.8,1]]"
    

我的测试 Lambda 调用成功。但是,如果您将模板硬编码为:


    "query-fixed": 
        "param": "[[\"kurlo jack\'s book\",\"Adventure Books\",8.8,1]]"
    

我收到与您在上面收到的相同的错误消息。不幸的是,第二种变体是 API Gateway 为 Lambda 调用生成的。

解决方法可能涉及使用模板将用斜杠转义的单引号替换为两个斜杠。见Replace a Substring of a String in Velocity Template Language

我会在内部跟进 Lambda 并在我听到任何消息或有功能性解决方法时进行更新。

【讨论】:

它确实帮助我解决了这个问题。我已经在你的回答中更新了解决方案【参考方案3】:

尝试根据this W3Schools page 中定义的内容将' 的编码更改为 %27(具有讽刺意味的是,他们的示例也没有对单引号进行编码,我猜它是因为它属于“支持”的 ASSCI 集字符)

【讨论】:

【参考方案4】:

请务必在.escapeJavaScript(data) 之后将.replaceAll("\\'","'") 添加到您的请求正文直通模板中

我从 AWS 的文档中发现这一点对这个问题非常有帮助:

$util.escapeJavaScript()

使用 JavaScript 字符串规则转义字符串中的字符。

注意此函数会将任何常规单引号 (') 转换为 转义的 (\')。但是,转义的单引号在 JSON。因此,当此函数的输出用于 JSON 属性,您必须将任何转义的单引号 (\') 转回常规 单引号 (')。这在以下示例中显示: $util.escapeJavaScript(data).replaceAll("\\'","'")

【讨论】:

我正在尝试这个,但我只是收到内部服务器错误。 "query": #foreach($queryParam in $input.params().querystring.keySet()) "$queryParam": "$util.escapeJavaScript($input.params().querystring.get($queryParam)).replace(\"\\'\",\"'\")" #if($foreach.hasNext),#end #end

以上是关于AWS Lambda 错误:当 url 参数包含 JSON 数组时,“无法将请求正文解析为 json”的主要内容,如果未能解决你的问题,请参考以下文章

Terraform:为调用 Lambda 的 AWS API Gateway 创建 url 路径参数?

使用 graphql、aws lambda 和无服务器框架的多个 url 路径选项错误

如何使用 GET 请求将参数传递给 AWS Lambda 函数?

AWS Lambda - 访问被拒绝错误 - GetObject

AWS Lambda,API Gateway 返回 Malformed Lambda 代理响应,502 错误

AWS lambda 函数在超时错误后停止工作