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

Lambda中DynamoDocumentClient未自动反序列化结果问题排查

问题:DynamoDBDocumentClient未自动反序列化结果,及SS类型转换优化

我编写了一个Lambda函数从DynamoDB获取记录,按AWS文档配置了DynamoDBDocumentClient(ddbDocClient),配置文件ddbDocClient.js代码如下:

const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");

const REGION = "us-west-2"

const ddbClient = new DynamoDBClient({ region: REGION });

const marshallOptions = {
    convertEmptyValues: false, // false, by default.
    removeUndefinedValues: false, // false, by default.
    convertClassInstanceToMap: false, // false, by default.
};

const unmarshallOptions = {
    wrapNumbers: false, // false, by default.
};

const translateConfig = { marshallOptions, unmarshallOptions };

const ddbDocClient = DynamoDBDocumentClient.from(ddbClient, translateConfig);

module.exports.ddbDocClient = ddbDocClient;

随后使用该客户端执行查询操作,代码如下:

const { ddbDocClient } = require("./ddbDocClient.js");
const { QueryCommand } = require("@aws-sdk/client-dynamodb");

const listsTableName = "my_list_name";

/// Fetches lists owned by the current user
async function getListIDs(userid) {

    const params = {
        TableName: listsTableName,
        IndexName: 'owner-index',
        KeyConditionExpression: '#owner = :owner',
        ExpressionAttributeNames: { "#owner": "owner" },
        ExpressionAttributeValues: {":owner": { "S": userid }}
    };
    const command = new QueryCommand(params);

    const dynamoData = await ddbDocClient.send(command);
    const lists = dynamoData.Items;
    console.log(lists);
}

但返回结果仍是带S、SS等类型标记的原始格式:

[
  {
    things: { SS: [Array] },
    owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
    collaborator: { S: 'A845E8EF-956B-467D-B57B-6D959BB78C98' },
    id: { S: '0C629140-6651-43E9-8D9F-3E52EBAD94F3' }
  },
  {
    owner: { S: '0d5e789b-009b-4ba0-80a7-12065d0908b5' },
    things: { SS: [Array] },
    collaborator: { S: 'ttttt' },
    id: { S: 'xxxxx89b-009b-4ba0-80a7-12065d0908b5' }
  }
]

我原本认为DocumentClient应该自动完成反序列化,目前只能手动处理,还需额外将SS类型的Set转换为数组:

const lists = dynamoData.Items;

// From DynamoDB JSON
var unmarshalledLists = lists.map((i) => unmarshall(i));

if (unmarshalledLists.length > 0) {
    // If we have at least 1 list we need to convert the things Set to Array
    unmarshalledLists.forEach(function(list) {
        const things = Array.from(list.things);
        list.things = things;
    });
    return unmarshalledLists;
} else {
    // No results to return
    throw("No lists found");
}

请问:

  1. 哪里操作错误导致无法自动反序列化?
  2. 是否有更简洁的方法将SS结果转换为数组?

解答

1. 自动反序列化失效的原因

核心错误是使用了错误的QueryCommand来源:你导入的是@aws-sdk/client-dynamodb中的QueryCommand,这是针对原始DynamoDB客户端的命令,不会触发DocumentClient的自动序列化/反序列化逻辑。

正确的做法是从@aws-sdk/lib-dynamodb导入QueryCommand,这个库才是为DocumentClient设计的配套命令集,能自动处理参数的marshall(序列化)和结果的unmarshall(反序列化)。

修正后的查询代码

const { ddbDocClient } = require("./ddbDocClient.js");
// 从lib-dynamodb导入QueryCommand
const { QueryCommand } = require("@aws-sdk/lib-dynamodb");

const listsTableName = "my_list_name";

async function getListIDs(userid) {
    const params = {
        TableName: listsTableName,
        IndexName: 'owner-index',
        KeyConditionExpression: '#owner = :owner',
        ExpressionAttributeNames: { "#owner": "owner" },
        // 无需手动添加类型标记,直接传入原始值即可
        ExpressionAttributeValues: {":owner": userid}
    };
    const command = new QueryCommand(params);

    const dynamoData = await ddbDocClient.send(command);
    const lists = dynamoData.Items;
    // 此时lists已经是反序列化后的普通对象,不再有S/SS标记
    console.log(lists);
    return lists;
}

2. 简化SS转数组的方法

默认情况下,DocumentClient会把SS类型反序列化为Set对象。如果想直接得到数组,无需手动遍历转换,只需在配置DocumentClient的unmarshallOptions中添加convertSetsToArrays: true即可。

修正后的配置文件ddbDocClient.js

const { DynamoDBDocumentClient } = require("@aws-sdk/lib-dynamodb");
const { DynamoDBClient } = require("@aws-sdk/client-dynamodb");

const REGION = "us-west-2"

const ddbClient = new DynamoDBClient({ region: REGION });

const marshallOptions = {
    convertEmptyValues: false,
    removeUndefinedValues: false,
    convertClassInstanceToMap: false,
};

const unmarshallOptions = {
    wrapNumbers: false,
    // 添加该配置,自动将Set转换为数组
    convertSetsToArrays: true
};

const translateConfig = { marshallOptions, unmarshallOptions };

const ddbDocClient = DynamoDBDocumentClient.from(ddbClient, translateConfig);

module.exports.ddbDocClient = ddbDocClient;

这样修改后,查询返回的things字段会直接是数组类型,不需要再手动调用Array.from()处理。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 00:28:11