You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在AWS API Gateway VLT映射模板中正确转义JSON?

问题描述

我正在通过AWS API Gateway使用Velocity模板语言(VTL)转换事件体后向EventBridge发布事件,遇到了MalformedDetail错误。

原始事件体

{
    "ordersDelivered": [
        {
            "orderId": "a0874e2c-4ad3-4fda-8145-18cc51616ecd",
            "address": {
                "line2": "10 Broad Road",
                "city": "Altrincham",
                "zipCode": "WA15 7PC",
                "state": "Cheshire",
                "country": "United Kingdom"
            }
        }
    ]
}

初始VTL模板

#set($context.requestOverride.header.X-Amz-Target = "AWSEvents.PutEvents")
#set($context.requestOverride.header.Content-Type = "application/x-amz-json-1.1")

#set($inputRoot = $input.path('$'))
{
"Entries": [
    #foreach($elem in $inputRoot.ordersDelivered)
    {
        "Resources" : ["$context.authorizer.clientId"],
        "Detail" : "$util.escapeJavaScript($elem)",
        "DetailType" : "OrderDelivered",
        "EventBusName" : "hk-playground-more-sole",
        "Source" : "delivery"
    }#if($foreach.hasNext),#end
    #end
]
}

错误日志

调用后收到EventBridge返回的格式错误:

Endpoint request body after transformations: 
{
"Entries": [
        {
        "Resources" : [""],
        "Detail" : "{orderId=a0874e2c-4ad3-4fda-8145-18cc51616ecd, address={line2=10 Broad Road, city=Altrincham, zipCode=WA15 7PC, state=Cheshire, country=United Kingdom}}",
        "DetailType" : "OrderDelivered",
        "EventBusName" : "hk-playground-more-sole",
        "Source" : "delivery"
    }    ]
}

Sending request to https://events.{aws-region}.amazonaws.com/?Action=PutEvents
Received response. Status: 200, Integration latency: 32 ms
Endpoint response headers: {x-amzn-RequestId=6cd086bf-5147-4418-9498-b467ed2b6b58, Content-Type=application/x-amz-json-1.1, Content-Length=104, Date=Thu, 15 Sep 2022 10:17:44 GMT}
Endpoint response body before transformations: {"Entries":[{"ErrorCode":"MalformedDetail","ErrorMessage":"Detail is malformed."}],"FailedEntryCount":1}
Method response body after transformations: {"Entries":[{"ErrorCode":"MalformedDetail","ErrorMessage":"Detail is malformed."}],"FailedEntryCount":1}

我尝试过用$util.toJson($elem)替代$util.escapeJavaScript($elem),但Detail变成空字符串并返回400错误;也尝试直接用JSONPath读取ordersDelivered,但错误依旧。


解决方案

问题出在$elem是Velocity内部对象,直接调用$util.escapeJavaScript会输出对象的toString格式(非标准JSON),而$util.toJson对这种对象处理异常导致空值。正确的做法是先通过JSONPath重新获取$elem的标准JSON字符串,再转义:

修改后的VTL模板:

#set($context.requestOverride.header.X-Amz-Target = "AWSEvents.PutEvents")
#set($context.requestOverride.header.Content-Type = "application/x-amz-json-1.1")

#set($inputRoot = $input.path('$'))
{
"Entries": [
    #foreach($elem in $inputRoot.ordersDelivered)
    #set($elemJson = $input.path('$.ordersDelivered[' + $foreach.index + ']'))
    {
        "Resources" : ["$context.authorizer.clientId"],
        "Detail" : "$util.escapeJavaScript($elemJson)",
        "DetailType" : "OrderDelivered",
        "EventBusName" : "hk-playground-more-sole",
        "Source" : "delivery"
    }#if($foreach.hasNext),#end
    #end
]
}

解释

  • 用$foreach.index获取当前循环的索引,通过JSONPath$.ordersDelivered[$index]直接从原始输入中提取该条目的标准JSON字符串。
  • 再对这个JSON字符串执行$util.escapeJavaScript,确保双引号等特殊字符被正确转义,符合EventBridge要求的Detail字段格式(必须是转义后的JSON字符串)。

另外,如果你不需要Resources字段里的clientId,可以留空或者移除该字段,避免出现空数组的情况。


内容的提问来源于stack exchange,提问作者Hemant

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 08:35:31