【问题标题】:AWS Can not deserialize instance of java.lang.String out of START_OBJECTAWS 无法反序列化 START_OBJECT 之外的 java.lang.String 实例
【发布时间】:2016-09-06 10:32:22
【问题描述】:

我创建了一个 Lambda 函数,我想在 API 网关的帮助下通过 URL 访问它。

我已经全部设置好了,我还在 API Gateway 中创建了一个 application/json 身体映射模板,如下所示:

{ 
    "input": "$input.params('input')",
}

然后我触发如下所示的 HTTP GET 请求:

https://dmquh95ckh.execute-api.eu-west-1.amazonaws.com/prod/OtoTestFunction?input=test

我的 Java 处理程序类如下所示:

public class LambdaFunctionHandler implements RequestHandler<String, String> {

    @Override
    public String handleRequest(String input, Context context) {
        context.getLogger().log("Input: " + input);
        return "Test completed."+input;
    }
}

这是完整的错误信息:

{
  "errorMessage": "An error occurred during JSON parsing",
  "errorType": "java.lang.RuntimeException",
  "stackTrace": [],
  "cause": {
    "errorMessage": "com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@68c4039c; line: 1, column: 1]",
    "errorType": "java.io.UncheckedIOException",
    "stackTrace": [],
    "cause": {
      "errorMessage": "Can not deserialize instance of java.lang.String out of START_OBJECT token\n at [Source: lambdainternal.util.NativeMemoryAsInputStream@68c4039c; line: 1, column: 1]",
      "errorType": "com.fasterxml.jackson.databind.JsonMappingException",
      "stackTrace": [
        "com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)",
        "com.fasterxml.jackson.databind.DeserializationContext.mappingException(DeserializationContext.java:835)",
        "com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:59)",
        "com.fasterxml.jackson.databind.deser.std.StringDeserializer.deserialize(StringDeserializer.java:12)",
        "com.fasterxml.jackson.databind.ObjectReader._bindAndClose(ObjectReader.java:1441)",
        "com.fasterxml.jackson.databind.ObjectReader.readValue(ObjectReader.java:1047)"
      ]
    }
  }
}

【问题讨论】:

  • 这是在调用 Java 函数之前还是之后发生的?您的“输入:”日志消息是否显示在日志中?

标签: java amazon-web-services aws-lambda aws-api-gateway


【解决方案1】:

当我将输入参数的类型从 String 更改为 Object 时,它在所有情况下都对我有用。

public class LambdaFunctionHandler implements RequestHandler<Object, String> {

  @Override
  public String handleRequest(Object input, Context context) {
    String data= input != null ? input.toString() : "{}";
    context.getLogger().log("Input: " + data);
    return "Test completed."+data;
  }
}

****************************** 于 2021 年 3 月 12 日添加 **************** ***********

在完成了几个 Lambda 实现之后,我意识到输入参数只不过是 JSON 结构的纯字符串表示或 Map 表示。 对于映射表示,Key 是属性的名称,并且值是 (1) 如果它是原始值,则为 String 或 (2) 如果具有多个值,则为 List,是另一个 Map 或另一个JSON 结构。您可以使用以下方法恢复 JSON 表示:

    if(input instanceof String)
    {
        String lambdaInputJsonStr = (String)input;
    }
    else if(input instanceof Map)
    {
        String lambdaInputJsonStr = gson.toJson((Map)input);
    }

【讨论】:

  • 我在关注github.com/awsdocs/aws-lambda-developer-guide/blob/main/…时陷入了使用String的同样陷阱
  • 这几乎正是我面临的问题,最终使用: implements RequestHandler, String> 而不是我复制的具有 Map
  • 将数据类型从 String 更改为 Object 也对我有用。谢谢!
  • 对我不起作用我得到“无法从 START_OBJECT 令牌中反序列化 java.lang.String 的实例”
【解决方案2】:

这是 Lambda 反序列化期间的错误消息。

您的 API Gateway 映射模板正在发送一个 JSON 对象,但您的处理程序需要一个字符串。从 API Gateway 发送原始字符串,或者更新您的处理程序以使用与您的模板输出对应的 POJO。

public class MyPojo {
   private String input;
   public String getInput() { return input; }
   public void setInput(String input) { this.input = input; }
}

见: http://docs.aws.amazon.com/lambda/latest/dg/java-programming-model-req-resp.html

【讨论】:

  • “要么从 API 网关发送原始字符串”:这是怎么做到的?答案是指哪个“模板输出”?
【解决方案3】:

我尝试使用 Object 作为参数类型以及 Pojo 类,它在某些情况下有效,但是在使用 API 网关 URL 从浏览器发出请求时,它失败并给出了上述错误。至少花了 2-3 个小时来找出正确的签名,这在大多数情况下都可以工作,如下所示。但是,这是针对 hello world 的示例,您显然可以根据需要自定义输入。

public class LambdaFunctionHandler implements RequestHandler<***Map<String,Object>,***  Customer> { 
    @Override
    public Customer handleRequest(***Map<String,Object> input***, Context context) {

    }
}

【讨论】:

    【解决方案4】:

    InputStream 应该能够处理任何输入。

    参考: https://docs.aws.amazon.com/lambda/latest/dg/java-handler.html

    InputStream – 事件是任何 JSON 类型。运行时将文档的字节流不加修改地传递给处理程序。您反序列化输入并将输出写入输出流。

    public class Handler implements RequestHandler<InputStream, String> {
    @Override
        public String handleRequest(InputStream event, Context context) {
    

    【讨论】:

      【解决方案5】:

      错误消息试图说“由于input 是一个字符串,我希望它以引用" 开头。但我看到的是{”。这就是为什么将input 类型更改为ObjectMap&lt;String,Object&gt;MyPojo 会使解析器满意。

      如果input 真的应该是一个字符串,那么有效负载值本身必须以" 开头。例如,String payload = "\"string input\""

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-01
        • 2013-10-23
        • 2019-12-13
        • 2019-02-08
        • 2017-09-23
        • 1970-01-01
        • 2018-05-22
        • 1970-01-01
        相关资源
        最近更新 更多