java - AWS @LambdaFunction 无法反序列化为 POJO

标签 java aws-lambda jackson

我将 Spring Boot (2.26) 与适用于 Java 的 AWS 开发工具包 (1.11.761) 结合使用。

我的问题是 @LambdaFunction 无法反序列化到我的 POJO,失败原因为:

"com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot construct instance of com.example.Sentence (although at least one Creator exists): no String-argument constructor/factory method to deserialize from String value ('{"end": 16, "id": 1, "start": 0, "text": "Hello, Foobar!!!", "type": "SENTENCE", "uuid": "de0134a93c1f4f2dbd910ae39438359d", "warnings": []}') at [Source: (byte[])""{\"end\": 16, \"id\": 1, \"start\": 0, \"text\": \"Hello, Foobar!!!\", \"type\": \"SENTENCE\", \"uuid\": \"de0134a93c1f4f2dbd910ae39438359d\", \"warnings\": []}""; line: 1, column: 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 注释并手动调用会给出 byte[] 格式的转义 JSON 字符串,即 '\"{\"id\":\123}\"'。如果我不手动取消转义并删除前导和尾随引号,我会遇到同样的失败。

看来,如果我要求 String 作为返回类型,SDK 将处理取消转义它,但如果我要求 POJO,它只会将转义的 byte[] 交给 Jackson,而 Jackson 会失败。

我可以在 Jackson 或 SDK 上进行任何配置来防止这种情况吗?我已经尝试将 Jackson 从 AWS SDK 的 Maven 依赖项中排除,以防版本冲突,但得到了相同的结果。

最佳答案

您需要一种方法让 Jackson 构建您的 Sentence 对象。有两种方法可以实现此目的:

  1. 添加一个空的构造函数以及 getter 和 setter 方法,也许您需要在每个字段(uuid 除外)上使用 @JsonProperty("fieldName")
  2. 添加一个带有 @JsonCreator 的构造函数,并为构造函数的每个参数添加 @JsonProperty("filedName"),我也会添加 getter 方法
@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;
}

在我看来,第二种方法更好,以便使用不可变对象(immutable对象)

关于java - AWS @LambdaFunction 无法反序列化为 POJO,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61170798/

相关文章:

aws-lambda - 调用 amazondax 服务时获取权限异常

java - request.setAttribute() 和 model.addAttribute 之间有什么区别?

java - 如何验证wrapper.conf中的Java参数

java - XJC Maven 插件(jaxb2-maven-plugin) Java 11 迁移问题

python - 更新 AWS Lambda 文件的权限以使其可执行

node.js - 如何针对 Alexa 技能的错误和警告发出警报?

java - @org.springframework.data.annotation.Transient 字段仍然序列化

java - 从 json 字符串中删除字段

java - 无法写入 JSON : Direct self-reference leading to cycle

java .contains() 查找数组