0

我正在使用 Spring Boot (2.26) 和 AWS SDK for Java (1.11.761)。

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

“com.fasterxml.jackson.databind.exc.MismatchedInputException:无法构造实例com.example.Sentence(尽管至少存在一个创建者):没有从字符串值反序列化的字符串参数构造函数/工厂方法('{“end”:16,“id “:1,“开始”:0,“文本”:“你好,Foobar!!!”,“类型”:“句子”,“uuid”:“de0134a93c1f4f2dbd910ae39438359d”,“警告”:[]}')在[来源:(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 注释并手动调用会给出一个字节[] 格式的转义JSON 字符串,即'\"{\"id\":\123}\"'。如果我不手动取消转义并删除前导引号和尾随引号,我会遇到同样的失败。

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

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

4

1 回答 1

0

您需要一种方法让杰克逊构造您的 Sentence 对象。有两种方法可以做到这一点:

  1. 添加一个空的构造函数和 getter 和 setter 方法,也许你需要@JsonProperty("fieldName")在每个字段上(除了 uuid)
  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;
}

在我的偏好中,为了使用不可变对象,第二种方法更好

于 2020-04-13T13:21:42.047 回答