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

Java SDK v2扫描DynamoDB列表嵌套Map属性映射异常解决方案问询

解决方案

你遇到的异常是因为DynamoDB Enhanced Client没有默认注册List<Map<String,String>>类型的转换器,可通过以下两种方式解决:

方案1:使用自定义转换器(推荐,适配性最强)

第一步:实现自定义属性转换器

实现AttributeConverter接口,完成Java对象和DynamoDB AttributeValue的双向转换:

import software.amazon.awssdk.enhanced.dynamodb.AttributeConverter;
import software.amazon.awssdk.enhanced.dynamodb.AttributeValueType;
import software.amazon.awssdk.enhanced.dynamodb.EnhancedType;
import software.amazon.awssdk.services.dynamodb.model.AttributeValue;

import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class AccountListConverter implements AttributeConverter<List<Map<String, String>>> {

    @Override
    public AttributeValue transformTo(List<Map<String, String>> input) {
        // 将Java List<Map>转为DynamoDB的L类型(列表类型)
        List<AttributeValue> listValues = input.stream()
                .map(map -> AttributeValue.builder().m(
                        map.entrySet().stream()
                                .collect(Collectors.toMap(
                                        Map.Entry::getKey,
                                        entry -> AttributeValue.builder().s(entry.getValue()).build()
                                ))
                ).build())
                .collect(Collectors.toList());
        return AttributeValue.builder().l(listValues).build();
    }

    @Override
    public List<Map<String, String>> transformFrom(AttributeValue input) {
        // 将DynamoDB的L类型转回Java List<Map>
        return input.l().stream()
                .map(item -> item.m().entrySet().stream()
                        .collect(Collectors.toMap(
                                Map.Entry::getKey,
                                entry -> entry.getValue().s()
                        ))
                )
                .collect(Collectors.toList());
    }

    @Override
    public EnhancedType<List<Map<String, String>>> type() {
        return EnhancedType.listOf(EnhancedType.mapOf(String.class, String.class));
    }

    @Override
    public AttributeValueType attributeValueType() {
        return AttributeValueType.L;
    }
}

第二步:在StaticTableSchema中关联转换器

修正你现有代码的属性定义,补充getter和转换器配置即可:

final StaticTableSchema<Target> tableSchema = StaticTableSchema.builder(Target.class)
        .newItemSupplier(Target::new)
        .addAttribute(String.class, a -> a.name("Name")
                .getter(Target::getName)
                .setter(Target::setName)
                .tags(DynamoDbPartitionKeyTag.create()) // 标记分区键
        )
        .addAttribute(EnhancedType.listOf(EnhancedType.mapOf(String.class, String.class)), a -> a.name("Accounts")
                .getter(Target::getAccounts) // 补充缺失的getter配置
                .setter(Target::setAccounts)
                .attributeConverter(new AccountListConverter()) // 绑定自定义转换器
        )
        .build();

方案2:使用注解简化配置(适合优先用注解的场景)

如果你不用手动写StaticTableSchema,直接在DynamoDbBean的字段上加转换器注解即可:

@DynamoDbBean
public class Target {
    private String name;
    private List<Map<String,String>> accounts;

    @DynamoDbPartitionKey
    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @DynamoDbConvertedBy(AccountListConverter.class)
    public List<Map<String, String>> getAccounts() {
        return accounts;
    }

    public void setAccounts(List<Map<String, String>> accounts) {
        this.accounts = accounts;
    }
}

直接用DynamoDbEnhancedClient.table("你的表名", TableSchema.fromBean(Target.class))就能完成映射,不需要手动写StaticTableSchema。

注意事项

  • 你现有代码中类名不一致(一会儿是Target一会儿是TargetCompany),请统一类名避免编译错误
  • 如果你的Map里的值不只有String类型,可在转换器的transformTo和transformFrom方法中扩展对应类型的转换逻辑即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 12:36:02