使用VTL解析Step Function输出时,如何正确序列化API网关响应Body?
API Gateway VTL解析Step Functions响应并序列化JSON体
问题描述
需要通过VTL从API Gateway与Step Functions集成的响应中,解析出statusCode和body,最终返回如下格式的方法响应:
Request status: 201 Response body: {"firstName":"He","lastName":"Man","email":"he.man@eternia.com"}
集成响应的原始结构(已移除无关属性):
{ "output": "{\"statusCode\":201,\"body\":{\"firstName\":\"He\",\"lastName\":\"Man\",\"email\":\"he.man@eternia.com\"}}" }
尝试过的VTL代码及问题:
- 初始代码(状态码未更新,响应体为空):
#set ($output = $util.parseJson($input.json('$.output'))) #set ($statusCode = $output.statusCode) #set ($context.responseOverride.status = $statusCode) $output.body
返回结果:
Request status: 200 Response body: <empty>
- 调整后代码(状态码正确,但body输出为对象格式而非标准JSON):
#set ($bodyObj = $util.parseJson($input.body)) #set ($output = $util.parseJson($bodyObj.output)) #set ($context.responseOverride.status = $output.statusCode) $output.body
返回结果:
Request status: 201 Response body: {firstName=He, lastName=Man, email=he.man@eternia.com}
已确认$output解析正常:
#set ($output = $util.parseJson($input.json('$.output'))) $output
返回结果:
Request status: 200 Response body: {"statusCode":201,"body":{"firstName":"He","lastName":"Man","email":"he.man@eternia.com"}}
核心问题:API Gateway VTL没有类似AppSync的$util.toJson函数,如何将$output.body正确序列化为标准JSON字符串?
解决方案
方法1:直接截取原始JSON片段
利用output本身是JSON字符串的特性,直接提取其中的body部分,无需将body解析为对象:
#set ($rawOutput = $input.json('$.output')) #set ($output = $util.parseJson($rawOutput)) #set ($context.responseOverride.status = $output.statusCode) #set ($bodyStart = $rawOutput.indexOf('"body":') + 7) #set ($bodyEnd = $rawOutput.lastIndexOf('}')) $rawOutput.substring($bodyStart, $bodyEnd)
说明:通过定位"body":的起始位置,截取原始JSON中body对应的完整JSON片段,直接输出即可得到标准JSON格式的响应体。
方法2:调用Java Jackson工具类序列化对象
API Gateway VTL支持调用Java类,使用Jackson的ObjectMapper将解析后的body对象序列化为JSON:
#set ($bodyObj = $util.parseJson($input.body)) #set ($output = $util.parseJson($bodyObj.output)) #set ($context.responseOverride.status = $output.statusCode) #set ($mapper = new com.fasterxml.jackson.databind.ObjectMapper()) $mapper.writeValueAsString($output.body)
说明:通过实例化Jackson的ObjectMapper,调用其writeValueAsString方法将Java对象转换为标准JSON字符串。
方法3:修正初始代码的输入处理逻辑
初始代码的问题在于$input.json('$.output')的使用方式,改用$input.body先解析整个响应体,再结合方法2的序列化逻辑,也能得到正确结果:
#set ($fullResponse = $util.parseJson($input.body)) #set ($output = $util.parseJson($fullResponse.output)) #set ($context.responseOverride.status = $output.statusCode) #set ($mapper = new com.fasterxml.jackson.databind.ObjectMapper()) $mapper.writeValueAsString($output.body)
关键原理
- 当使用
$util.parseJson解析output后,$output.body会被转换为Java对象(如LinkedHashMap),直接输出时会采用Java对象的默认toString()格式,而非JSON结构。 - API Gateway VTL未内置JSON序列化工具函数,但可通过字符串截取或调用Java JSON工具类两种方式实现需求。
内容的提问来源于stack exchange,提问作者villekr
相关产品推荐
相关产品推荐

