AWS API Gateway - 集成响应正文映射
Posted
技术标签:
【中文标题】AWS API Gateway - 集成响应正文映射【英文标题】:AWS API Gateway - Integration Response body mapping 【发布时间】:2018-05-02 09:35:33 【问题描述】:在 AWS API Gateway 集成响应正文映射中,我有以下代码:
#set($inputRoot = $input.path('$.Item'))
[
#foreach($elem in $inputRoot.Events)
"id": $elem.id,
"from" : $elem.from,
"to" : $elem.to,
"spent" : $elem.spent,
#if("$!elem.comment" != "")
"comment": $elem.comment,
#end
"project" :
"id" : $elem.project.id,
"number" : $elem.project.number,
"name" : $elem.project.name
#if($foreach.hasNext),#end
#end
]
数据来自查询 DynamoDB 表的 lambda 函数
API 网关返回数据如下:
[
"id": 123443214,
"from" : 19:34,
"to" : 22:30,
"spent" : 02:56,
"project" :
"id" : 4321,
"number" : CIB,
"name" : Backend
,
"id": 12341234,
"from" : 19:34,
"to" : 22:30,
"spent" : 02:56,
"project" :
"id" : 12341234,
"number" : CIB,
"name" : Backend
]
所以它已经格式化了。如何让 APi Gateway 返回未格式化的响应?所以它只是纯 json,没有折线、缩进等?
提前致谢!
【问题讨论】:
【参考方案1】:(简短的初步说明:您在 JSON 字符串值周围缺少一些引号)。
可以使用##
删除换行符,使用#**#
删除缩进,如下所示,但模板看起来有点难看:
#set($inputRoot = $input.path('$.Item'))##
[##
#foreach($elem in $inputRoot.Events)##
##
#**#"id":$elem.id,##
#**#"from": $elem.from,##
#**#"to":$elem.to,##
#**#"spent":$elem.spent,##
#if("$!elem.comment" != "")##
#* *#"comment":$elem.comment,##
#end##
#**#"project":##
#**#"id":$elem.project.id,##
#**#"number":"$elem.project.number",##
#**#"name":"$elem.project.name"##
##
##
#if($foreach.hasNext),#end##
#end##
]##
由于缩进一开始在这里的唯一原因是模板的可读性,我会转向另一个方向。
例如,您可以使用org.json 在您的 View servlet 中添加一个后处理整洁的格式化程序:
import org.json.JSONObject;
....
Writer writer = new StringWriter();
getVelocityView().merge(template, context, writer);
String compactJSON = new JSONObject(writer.toString()).toString();
response.getWriter().write(compactJSON);
但是这仅适用于小型 JSON 文件,因为响应被缓冲到内存中,所以让我们继续寻找更优雅的解决方案。
要走的路是预处理您的模板,使用自定义 ResouceLoader。
CompactJSONResourceLoader.java
package my.custom.loader;
import java.io.InputStream;
import java.io.IOException;
import org.apache.commons.collections.ExtendedProperties;
import org.apache.velocity.exception.ResourceNotFoundException;
import org.apache.velocity.runtime.resource.Resource;
import org.apache.velocity.runtime.resource.loader.ResourceLoader;
import org.apache.velocity.runtime.resource.loader.ResourceLoaderFactory;
public class CompactJSONResourceLoader extends ResourceLoader
protected ResourceLoader innerLoader = null;
@Override
public void init(ExtendedProperties configuration)
try
String innerLoaderID = configuration.getString("innerLoader") + ".resource.loader";
String innerLoaderClass = rsvc.getConfiguration().getString(innerLoaderID + ".class");
innerLoader = ResourceLoaderFactory.getLoader(rsvc, innerLoaderClass);
ExtendedProperties innerConfiguration = rsvc.getConfiguration().subset(innerLoaderID);
innerLoader.commonInit(rsvc, innerConfiguration);
innerLoader.init(innerConfiguration);
catch (Exception e)
log.error("could not initialize CompactJSONResourceLoader inner loader", e);
protected class CompactJSONInputStream extends InputStream
InputStream innerStream = null;
boolean insideQuotes = false;
public CompactJSONInputStream(InputStream innerStream)
this.innerStream = innerStream;
@Override
public int read() throws IOException
int ch;
do
ch = innerStream.read();
if (insideQuotes)
if (ch == '"') insideQuotes = false;
break;
else if (!Character.isWhitespace(ch))
if (ch == '"') insideQuotes = true;
break;
while (ch != -1);
return ch;
@Override
public InputStream getResourceStream(String source) throws ResourceNotFoundException
return new CompactJSONInputStream(innerLoader.getResourceStream(source));
@Override
public boolean isSourceModified(Resource resource)
return innerLoader.isSourceModified(resource);
@Override
public long getLastModified(Resource resource)
return innerLoader.getLastModified(resource);
然后您需要使用以下属性配置 Velocity:
resource.loader = compact
compact.resource.loader.class = my.custom.loader.CompactJSONResourceLoader
compact.resource.loader.innerLoader = 文件
(当然,您可以将file
替换为您当前使用的资源加载器)。
【讨论】:
我要补充一点,建议的自定义 ResourceLoader 用于 Velocity 1.7 API。如果您使用的是 Velocity 2.0,则需要调整源代码,使其直接与 Readers 一起工作,而不是 InputStreams。 感谢您非常详细的回答!我使用 NodeJs,所以这个 ResourceLoader 可能不可用。但是由于我的 JSON 字符串值周围缺少引号,它工作得很好......我自己真是个愚蠢的错误 这个问题可能应该被标记为velocity.js
,而不是velocity
。但无论如何,这是一个有趣的回答,我很高兴,这是我第一次接受 velocity.js 速度的回答!
如何配置 AWS API Gateway 以使用它?不使用 Lambda 代理集成。
@Paya 那你就被丑陋的 cmets 解决方案困住了。以上是关于AWS API Gateway - 集成响应正文映射的主要内容,如果未能解决你的问题,请参考以下文章
AWS Lambda 和 API Gateway 响应集成问题
AWS API Gateway - Lambda 代理(集成请求) - 内部服务器错误
使用 AWS API Gateway 和 Java 处理错误响应状态代码/实体