AWS @LambdaFunction не может десериализоваться в POJO - PullRequest
0 голосов
/ 12 апреля 2020

Я использую Spring Boot (2.26) с AWS SDK для Java (1.11.761).

Моя проблема заключается в том, что @LambdaFunction не удается десериализовать мой POJO, сбой с:

"com.faster xml .jackson.databind.ex c .MismatchedInputException: Невозможно создать экземпляр com.example.Sentence (хотя существует хотя бы один создатель): нет конструктора аргумента строки / фабричного метода для десериализации из значения строки ('{"end": 16, "id": 1, "start": 0, "text": "Hello, Foobar !!!", "type": "SENTENCE", "uuid": "de0134a93c1f4f2dbd910ae39438359d", "warnings": []} ') в [Source: (byte []) "" { \ "end \": 16, \ "id \": 1, \ "start \": 0, \ "text \": \ "Hello, Foobar !!! \", \ "type \": \ "SENTENCE \ ", \" uuid \ ": \" de0134a93c1f4f2dbd910ae39438359d \ ", \" warnings \ ": []}" "; строка: 1, столбец: 1]

public interface TemplateLambda {
    @LambdaFunction(functionName="....")
    Sentence getSentence(TemplateInput input);

    @LambdaFunction(functionName="....")
    String getString(TemplateInput input);
}

@Data
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Sentence {

    @JsonIgnore
    private UUID uuid = UUID.randomUUID();

    private Long id;
    private String text;
    private String type;
    private List<Warning> warnings = new ArrayList<>();
    private Long start;
    private Long end;
}

Вызывается с помощью:

final ObjectMapper objectMapper = new ObjectMapper()
            .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);

final TemplateLambda lambda = LambdaInvokerFactory.builder()
            .lambdaClient(AWSLambdaClientBuilder.defaultClient())
            .objectMapper(objectMapper)
            .build(TemplateLambda.class);

TemplateInput input = new TemplateInput("Foobar");
try {
    String s = lambda.getString(input);
    Sentence sent = objectMapper.readValue(s, Sentence.class); // SUCCEEDS
    logger.info("THIS SUCCEEDS);

    Sentence output = lambda.getSentence(input); // FAILS
    logger.info("THIS FAILS");

} catch (Exception e) {
    e.printStackTrace();
}

Я также проверил, что пропуск аннотации @LambdaFunction и ручной вызов дает экранированную строку JSON в формате byte [], ie '\ "{\" id \ ": \ 123} \ "'. Если я не удаляю вручную это, удаляя начальные и конечные кавычки, я получаю тот же провал.

Похоже, что если я запрашиваю String в качестве возвращаемого типа, SDK будет иметь дело с его удалением, но если я попрошу POJO, он просто передаст экранированный байт [] Джексону, и Джексон не сможет.

Какую конфигурацию я могу сделать на Джексоне или в SDK, чтобы предотвратить это? Я уже пытался исключить Джексона из зависимостей Maven AWS SDk на случай, если я получаю конфликтующие версии, но получаю тот же результат.

1 Ответ

0 голосов
/ 13 апреля 2020

Вам нужен способ, чтобы Джексон мог построить ваш объект Sentence. sh это можно сделать двумя способами:

  1. добавить пустой метод конструктора и метода получения и установки, возможно вам потребуется @JsonProperty("fieldName") для каждого поля (кроме uuid)
  2. добавив конструктор с @JsonCreator на нем и @JsonProperty("filedName") для каждого аргумента конструктора, я бы тоже добавил метод получения
@JsonCreator
public Sentence(@JsonProperty("id")Long id,
     @JsonProperty("text")String text,
     @JsonProperty("type") String type,
     @JsonProperty("warnings") List<Warning> warnings,
     @JsonProperty("start") Long start,
     @JsonProperty("end") Long end) {
    this.id = id;
    this.text = text;
    this.type = type;
    this.warnings = new ArrayList<>();
    this.start = start;
    this.end = end;
}

В моем предпочтении второй метод лучше для того, чтобы использовать неизменяемые объекты

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...