Lambda-Dynamo API读取含数据Number Set返回空对象问题
问题原因与解决方案
核心原因
你遇到的问题是JSON序列化不支持JavaScript原生Set类型:
- 插入时用
new Set()生成的Number Set能被DynamoDB正确存储为NS类型; - 但通过DocumentClient读取后,返回的
associated_tournaments是JavaScript的Set对象; - 当Lambda将结果返回给API Gateway时,自动JSON序列化过程中,Set会被转换为空对象
{}(因为JSON没有原生Set类型的定义)。
解决方案
方案1:读取后手动转换为数组(推荐,不改变存储结构)
在读取数据后,把Set转为数组,确保JSON序列化能正常输出内容:
try { const result = await documentClient.send(new GetCommand({ TableName: process.env.TABLE_NAME, Key: { 'PK': '#LEADERBOARDS', 'SK': `LEADERBOARD#${leaderboardName}` }, ReturnConsumedCapacity: 'TOTAL' })) // 将Number Set转换为数组 if (result.Item?.associated_tournaments) { result.Item.associated_tournaments = Array.from(result.Item.associated_tournaments) } return result } catch (error) { return error }
方案2:插入时直接使用数组(放弃Set特性)
如果业务不需要DynamoDB Number Set的自动去重等特性,可以直接传入数组,读取后直接是可序列化的数组类型:
修改插入代码的associated_tournaments字段:
'associated_tournaments': requestBody.associated_tournaments // 直接传数组,DocumentClient会映射为DynamoDB List类型
注意:此方案会将存储类型从NS(Number Set)改为L(List),若依赖Set的唯一性约束,不建议使用。
方案3:配置DocumentClient自动转换(SDK v3特性)
通过自定义转换器,让SDK在读写时自动处理Set与数组的转换,无需手动修改业务代码:
import { DynamoDBDocumentClient, NativeAttributeValue } from "@aws-sdk/lib-dynamodb"; import { DynamoDB } from "@aws-sdk/client-dynamodb"; const client = new DynamoDB({}); const marshallOptions = { convertEmptyValues: false, removeUndefinedValues: true, convertClassInstanceToMap: true, }; const unmarshallOptions = { wrapNumbers: false, // 读取时自动将Number Set转为数组 deserializeNumberSet: (value: NativeAttributeValue) => Array.from(value as Set<number>), }; const translateConfig = { marshallOptions, unmarshallOptions }; // 用配置好的转换器初始化DocumentClient const documentClient = DynamoDBDocumentClient.from(client, translateConfig);
验证
修改后重新调用API,associated_tournaments会输出类似[7121, 7224]的数组内容,与DynamoDB控制台/CLI查询结果一致。
内容的提问来源于stack exchange,提问作者user22265191
相关产品推荐
相关产品推荐

