AWS Не удается десериализовать экземпляр java.lang.String из START_OBJECT

Я создал лямбда-функцию и хочу получить к ней доступ через URL-адрес с помощью шлюза API.

Я все это настроил, я также создал application/json шаблон отображения тела в API Gateway, который выглядит примерно так:

{ 
    "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)"
      ]
    }
  }
}

person Ondrej Tokar    schedule 11.05.2016    source источник
comment
Это происходит до вызова вашей функции Java или после? Отображается ли ваше сообщение Input: log в журналах?   -  person Mark B    schedule 11.05.2016


Ответы (5)


У меня это сработало во всех сценариях, когда я меняю тип входного аргумента с 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;
  }
}

************************* Добавлено 12 марта 2021 г. ******************* ********

После работы над парой реализаций Lambda я понял, что входной аргумент - это не что иное, как простое строковое представление структуры JSON или представления Map ‹String, Object›. Для представления карты Key - это имя атрибута, а его значение - (1) String, если это примитивное значение, или (2) List, если у него несколько значений, - это другая Map ‹String, Object› или другое Структура JSON. Вы можете восстановить представление JSON с помощью:

    if(input instanceof String)
    {
        String lambdaInputJsonStr = (String)input;
    }
    else if(input instanceof Map)
    {
        String lambdaInputJsonStr = gson.toJson((Map)input);
    }
person skvp    schedule 21.02.2019
comment
Я попал в ту же ловушку, когда использовал String, следуя github.com/awsdocs/aws-lambda-developer-guide/blob/main/ - person Big Pumpkin; 17.01.2021
comment
Это почти именно та проблема, с которой я столкнулся, в итоге я использовал: реализует RequestHandler ‹Map‹ String, Object ›, String› вместо примера, который я скопировал, в котором была Map ‹String, String› - person Matt; 22.01.2021
comment
У меня тоже сработало изменение типа данных со String на Object. Спасибо! - person Shrinath; 25.01.2021
comment
у меня не сработало Я получил Невозможно десериализовать экземпляр java.lang.String из токена START_OBJECT - person Abel ANEIROS; 20.05.2021

Это сообщение об ошибке во время десериализации Lambda.

Ваш шаблон сопоставления шлюза API отправляет объект JSON, но ваш обработчик ожидает строку. Либо отправьте необработанную строку из API Gateway, либо обновите обработчик, чтобы он использовал POJO, соответствующий выходным данным вашего шаблона.

i.e.

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.

person RyanG    schedule 11.05.2016
comment
Либо отправьте необработанную строку из API Gateway: как это сделать? К какому выходному шаблону относится ответ? - person Harald; 26.02.2018

Я пробовал использовать объект в качестве типа параметра, а также класс Pojo, и он работал в определенных сценариях, но при выполнении запроса из браузера с URL-адресом шлюза API он не удался и дал точную ошибку выше. Потратил не менее 2-3 часов на то, чтобы выяснить, какая правильная подпись, которая будет работать в большинстве случаев, находится ниже. Однако это для примера hello world, вы, очевидно, должны настроить свой ввод в соответствии с вашими требованиями.

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

    }
}
person Vikky    schedule 23.10.2019
comment
Большое спасибо, это устранило мою проблему - person animo3991; 25.10.2020

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) {
person Eugene    schedule 29.11.2020

Сообщение об ошибке пытается сказать, что, поскольку input является строкой, я ожидаю, что оно будет начинаться с кавычки ". Но вместо этого я вижу {. Вот почему изменение типа input на Object, Map<String,Object> или MyPojo сделало парсер счастливым.

Если input действительно должен быть String, само значение полезной нагрузки должно начинаться с ". Например, String payload = "\"string input\"".

person Big Pumpkin    schedule 18.01.2021