You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Jackson无法将JSON字符串反序列化为AWS Textract对象的问题

AWS Java SDK v2 Textract模型反序列化问题解决方案

问题描述

使用AWS Java SDK v2时,将JSON字符串反序列化为Textract的DocumentMetadata这类模型对象时,Jackson直接抛出错误,提示找不到合适的构造器(默认构造器或基于属性/委托的创建器)。由于SDK的模型类是只读的,无法添加Jackson注解;尝试过Gson也未解决,不想手动编写本地映射模型,寻求可行方案。

错误日志:

Cannot construct instance of `software.amazon.awssdk.services.textract.model.DocumentMetadata` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (StringReader); line: 1, column: 57] (through reference chain: com.amazon.fdmextractionserviceextractfromdocument.data.internal.AnalyseExpenseResponse["DocumentMetadata"]): com.fasterxml.jackson.databind.exc.InvalidDefinitionException
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `software.amazon.awssdk.services.textract.model.DocumentMetadata` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
 at [Source: (StringReader); line: 1, column: 57] (through reference chain: com.amazon.fdmextractionserviceextractfromdocument.data.internal.AnalyseExpenseResponse["DocumentMetadata"])
    at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
    at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1764)
    at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
    at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1209)
    at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1415)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:363)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:196)
    at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:129)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:325)
    at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:188)
    at com.fasterxml.jackson.databind.deser.DefaultDeserializationContext.readRootValue(DefaultDeserializationContext.java:322)
    at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4593)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3548)
    at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3516)
    at com.amazon.fdmextractionserviceextractfromdocument.data.TextractOutputBuilder.getTextractOutput(TextractOutputBuilder.kt:22)
    at com.amazon.fdmextractionserviceextractfromdocument.domainlogic.ExtractDataComponent.extractData(ExtractDataComponent.kt:12)
    at com.amazon.fdmextractionserviceextractfromdocument.service.ExtractDataActivity.extractData(ExtractDataActivity.kt:14)
    at com.amazon.fdmextractionserviceextractfromdocument.LambdaMain.handleRequest(LambdaMain.kt:23)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
    at java.base/java.lang.reflect.Method.invoke(Unknown Source)

可行解决方案

1. 使用AWS SDK自带的Jackson模块(最省心)

AWS SDK v2专门提供了适配自身模型的Jackson模块,直接用它就能解决构造器兼容问题,无需修改任何代码。

操作步骤:

  • 添加Maven依赖(版本需与你的AWS SDK保持一致):
<dependency>
    <groupId>software.amazon.awssdk</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>${aws.sdk.version}</version>
</dependency>
  • 初始化适配SDK模型的ObjectMapper:
import com.fasterxml.jackson.databind.ObjectMapper;
import software.amazon.awssdk.core.serialization.json.JsonSdkSerializer;

// 用SDK工具创建适配的ObjectMapper
ObjectMapper awsObjectMapper = JsonSdkSerializer.builder().build().objectMapper();

// 直接执行反序列化
String jsonContent = "你的JSON字符串";
AnalyseExpenseResponse response = awsObjectMapper.readValue(jsonContent, AnalyseExpenseResponse.class);

该模块会自动识别SDK模型的Builder构造逻辑,完美适配反序列化流程。

2. 使用SDK内置的Json解析器(兼容性最强)

如果不想依赖Jackson,可以直接用SDK自身的解析器,完全贴合模型的序列化逻辑:

import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.services.textract.model.DocumentMetadata;
import software.amazon.awssdk.core.serialization.json.JsonSdkParser;

// 将JSON字符串转为SDK标准字节格式
SdkBytes jsonBytes = SdkBytes.fromUtf8String(jsonContent);
// 创建SDK原生解析器
JsonSdkParser parser = JsonSdkParser.create();
// 直接解析为目标模型对象
DocumentMetadata metadata = parser.parse(jsonBytes, DocumentMetadata.SDK_DESERIALIZER);

这种方式不需要第三方库,完全依赖SDK自身能力,不存在兼容性问题。

3. 给自定义类的SDK字段添加Jackson反序列化器(局部适配)

如果只是你的自定义类(比如AnalyseExpenseResponse)中包含SDK模型字段,可以给该字段单独编写反序列化器:

import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import software.amazon.awssdk.core.SdkBytes;
import software.amazon.awssdk.core.serialization.json.JsonSdkParser;
import software.amazon.awssdk.services.textract.model.DocumentMetadata;

// 自定义反序列化器
public class DocumentMetadataDeserializer extends JsonDeserializer<DocumentMetadata> {
    @Override
    public DocumentMetadata deserialize(com.fasterxml.jackson.core.JsonParser p, DeserializationContext ctxt) throws IOException {
        // 将JSON节点转为字符串
        String json = p.readValueAsTree().toString();
        // 用SDK解析器处理
        JsonSdkParser parser = JsonSdkParser.create();
        return parser.parse(SdkBytes.fromUtf8String(json), DocumentMetadata.SDK_DESERIALIZER);
    }
}

// 在自定义类中标记字段使用该反序列化器
public class AnalyseExpenseResponse {
    @JsonDeserialize(using = DocumentMetadataDeserializer.class)
    private DocumentMetadata documentMetadata;

    // getter和setter方法
}

这样既无需修改SDK类,也能让Jackson正确解析该字段。

为什么Gson不好用?

Gson默认要求类有公开无参构造器或可直接赋值的字段,但AWS SDK v2的模型均为不可变对象,采用Builder模式创建,没有公开字段和无参构造器,因此直接用Gson无法解析。如果非要用Gson,需要为每个SDK模型编写TypeAdapter,工作量与手动编写本地模型相当,不如上述方案高效。

内容的提问来源于stack exchange,提问作者Sudhanshu Bhoi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 05:30:54