Spring Boot从DynamoDB读取Double触发NumberFormatException问题求助
问题:DynamoDB SDK将Double解析为Integer触发NumberFormatException
问题场景
开发Spring Boot应用时,使用AWS SDK从DynamoDB读取数据,遇到SDK错误地将Double类型字段按Integer解析,抛出NumberFormatException的问题。使用的AWS SDK版本为1.12.454,代码库中所有overallEnergy的引用均为Double类型。
实体类代码
import com.amazonaws.services.dynamodbv2.datamodeling.*; import lombok.*; import org.springframework.data.annotation.Id; import java.time.LocalDate; @Getter @Setter @NoArgsConstructor @AllArgsConstructor @DynamoDBTable(tableName = "my_table") public class MyEntity { @Id @Getter(value = AccessLevel.NONE) private MyKey myKey; // Other attributes... @DynamoDBAttribute(attributeName = "overall_energy") @DynamoDBTyped(DynamoDBMapperFieldModel.DynamoDBAttributeType.N) private Double overallEnergy; // Other attributes... }
DynamoDB中的目标数据
{ "overall_energy": { "N": "29985.689834184945" } }
错误日志
Jun 9 22:20:39 ip-10-55-167-190 web: at java.base/java.lang.Thread.run(Thread.java:833) ~[na:na] Jun 9 22:20:39 ip-10-55-167-190 web: Caused by: java.lang.NumberFormatException: For input string: "29985.689834184945" Jun 9 22:20:39 ip-10-55-167-190 web: at java.base/java.lang.NumberFormatException.forInputString(NumberFormatException.java:67) ~[na:na] Jun 9 22:20:39 ip-10-55-167-190 web: at java.base/java.lang.Integer.parseInt(Integer.java:668) ~[na:na] Jun 9 22:20:39 ip-10-55-167-190 web: at java.base/java.lang.Integer.valueOf(Integer.java:999) ~[na:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters$ToInteger$2.convert(StandardTypeConverters.java:773) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters$ToInteger$2.convert(StandardTypeConverters.java:770) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.StandardTypeConverters$1.unconvert(StandardTypeConverters.java:75) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter$DelegateConverter.unconvert(DynamoDBTypeConverter.java:109) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter$NullSafeConverter.unconvert(DynamoDBTypeConverter.java:128) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter$ExtendedConverter.unconvert(DynamoDBTypeConverter.java:88) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.unconvert(DynamoDBMapperFieldModel.java:146) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperFieldModel.unconvertAndSet(DynamoDBMapperFieldModel.java:164) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na] Jun 9 22:20:39 ip-10-55-167-190 web: at com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBMapperTableModel.unconvert(DynamoDBMapperTableModel.java:267) ~[aws-java-sdk-dynamodb-1.12.454.jar!/:na]
已尝试的解决步骤
- 创建自定义转换器
StringToDoubleTypeConverter,期望显式转换解决问题,仍抛出NumberFormatException - 移除
@DynamoDBTyped注解,让DynamoDBMapper隐式处理转换,问题未解决 - 修改DynamoDB中
overall_energy的值为两位小数,仍触发异常 - 将
overall_energy改为整数值,异常消失,但不符合应用需求
原因分析
问题根源在于AWS SDK的类型转换器匹配逻辑:当使用@DynamoDBTyped(DynamoDBAttributeType.N)时,SDK会优先尝试匹配范围更窄的严格数字类型,Integer的范围比Double更窄,导致SDK错误选择Integer转换器处理带小数的数字字符串。此外,实体类中其他字段(如MyKey)的注解配置可能干扰了转换器选择的上下文逻辑。
解决方案
方案1:显式绑定自定义类型转换器
创建自定义转换器,并通过@DynamoDBTypeConverted注解强制SDK使用该转换器处理字段,同时移除原有的@DynamoDBTyped注解避免冲突:
import com.amazonaws.services.dynamodbv2.datamodeling.DynamoDBTypeConverter; public class StringToDoubleConverter implements DynamoDBTypeConverter<String, Double> { @Override public String convert(Double object) { return object != null ? object.toString() : null; } @Override public Double unconvert(String object) { return object != null ? Double.valueOf(object) : null; } }
修改实体类字段:
@DynamoDBAttribute(attributeName = "overall_energy") @DynamoDBTypeConverted(converter = StringToDoubleConverter.class) private Double overallEnergy;
方案2:升级AWS SDK版本
旧版本SDK的类型匹配逻辑存在bug,升级到1.12.500及以上的1.12.x版本,新版本优化了数字类型转换器的选择逻辑,会优先根据实体类字段类型匹配对应转换器。
方案3:清理字段映射冲突
检查实体类中其他属性的注解配置,比如MyKey类中的字段是否存在不当的@DynamoDBTyped配置,避免干扰overallEnergy字段的转换器选择上下文。
内容的提问来源于stack exchange,提问作者Carlo Ligthart
相关产品推荐
相关产品推荐

