带有用于Java AWS Lambda的POJO输入处理程序的大写字段

时间:2017-11-06 09:37:25

标签: java json amazon-web-services jackson aws-lambda

根据此处描述的文档:http://docs.aws.amazon.com/lambda/latest/dg/java-programming-model-req-resp.html可以创建自己的POJO来序列化Java AWS Lambda的输入和输出。

然而,对于字段大写的输入请求,它似乎不能正常工作。例如,自定义资源lambda的输入格式如下:

{"RequestType":"Create", 
"ServiceToken":"arn:aws:lambda:....", 
"ResponseURL":"https://cloudformation-custom-resource-response-e...",
...}

这可以通过这个简单的MCVE代码轻松测试:

package test;

import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class TestLambda implements RequestHandler<TestLambda.TestEvent, String> {

    private static final Logger logger = LogManager.getLogger(TestLambda.class);

    @Override
    public String handleRequest(TestEvent event, Context context) {
         logger.debug(event.toString());    
         return null;
    }

    public static final class TestEvent {
        private String key1;

        private String Key2;

        private String key3;

        public String getKey1() {
            return key1;
        }

        public void setKey1(String key1) {
            this.key1 = key1;
        }

        public String getKey2() {
            return Key2;
        }

        public void setKey2(String key2) {
            Key2 = key2;
        }

        public String getKey3() {
            return key3;
        }

        public void setKey3(String key3) {
            this.key3 = key3;
        }

        @Override
        public String toString() {
            return "TestEvent{" +
                    "key1='" + key1 + '\'' +
                    ", Key2='" + Key2 + '\'' +
                    ", key3='" + key3 + '\'' +
                    '}';
        }
    }
}

然后在AWS控制台中为此lambda创建一个测试,并将其作为请求传递给以下json:

{
  "key3": "value3",
  "Key2": "value2",
  "Key1": "value1"
}

日志中的结果将是:

2017-11-06 09:30:13 16849696-c2d5-11e7-80c3-150a37863c42 DEBUG TestLambda:15 - TestEvent{key1='null', Key2='null', key3='value3'}

是否可以在不处理原始字节流的情况下对此输入进行反序列化,如同在该主题中所建议的那样?

  

您不应该依赖序列化框架的任何其他功能   例如注释。如果需要自定义序列化   行为,您可以使用原始字节流来使用您自己的   序列化。

如果我们无法为任何类型的事件自由创建POJO,那么在我看来这是Java AWS Lambdas的一个很大的限制。

3 个答案:

答案 0 :(得分:0)

在pojo中,将字段设为 public ,并将大小写与json字段完全相同。这意味着您应该拥有大写驼峰式字段,例如

public class TestEvent {
    public String Key1;

    public String Key2;

    public String key3;
}

我无法解释为什么会这样,但是我今天只是根据一位同事的建议尝试了一下,并且很有效。我知道它看起来并不优雅。但是至少比反序列化流更少的代码行。

答案 1 :(得分:0)

我已经在同一个问题上很久了,终于找到了答案:

Lambda有一个蓝图: https://github.com/awslabs/aws-apigateway-lambda-authorizer-blueprints/blob/0f7f3d933741a48c08c85feff267793f60b61a60/blueprints/java/src/io/AuthPolicy.java#L68

因此,基本上,您需要做的是重写JSON的get方法。并在此方法中返回Map 。现在,您可以在地图内使用大写的键来解决问题:

public Map<String, Object> getPolicyDocument() {
        Map<String, Object> serializablePolicy = new HashMap<>();
        serializablePolicy.put(VERSION, policyDocumentObject.Version);
        Statement[] statements = policyDocumentObject.getStatement();
        Map<String, Object>[] serializableStatementArray = new Map[statements.length];
        for (int i = 0; i < statements.length; i++) {
            Map<String, Object> serializableStatement = new HashMap<>();
            AuthPolicy.Statement statement = statements[i];
            serializableStatement.put(EFFECT, statement.Effect);
            serializableStatement.put(ACTION, statement.Action);
            serializableStatement.put(RESOURCE, statement.getResource());
            serializableStatement.put(CONDITION, statement.getCondition());
            serializableStatementArray[i] = serializableStatement;
        }
        serializablePolicy.put(STATEMENT, serializableStatementArray);
        return serializablePolicy;
    }

答案 2 :(得分:-3)

Java bean上的属性仍然是key2,全是小写,因为序列化框架可见的属性名是从getter派生的,而不是私有字段名。所以它仍会进入输入事件,寻找key2而不是Key2