DynamoDB中String Set反序列化失败:无法还原原始String Set的技术咨询
The Problem
I'm trying to marshall and unmarshall a String Set for DynamoDB using the @aws-sdk/util-dynamodb package, but the unmarshalling step doesn't restore the original Set — instead it returns an empty object. Here's my code:
import {marshall, unmarshall} from '@aws-sdk/util-dynamodb'; test('Marshall and Unmarshall Test', () => { const raw = { 'anArray': new Set([ 'Apple', 'Mango' ]) }; console.log(JSON.stringify(marshall(raw))); // {"anArray":{"SS":["Apple","Mango"]}} const marshalledResult = marshall(raw); console.log(JSON.stringify(unmarshall(marshalledResult))); // {"anArray":{}} });
The marshalling output looks correct, but I can't get the original String Set back after unmarshalling. What's the right way to handle String Sets when retrieving them from DynamoDB?
The Fixes
First, Why This Happens
By default, the unmarshall function doesn't convert DynamoDB's SS (String Set) type back to a JavaScript Set object. In some older package versions, you might even get an empty object instead of the expected array (the standard default conversion for SS is a plain array). The core issue is that the SDK prioritizes standard JS types (arrays) over Sets for broader compatibility, so we need to add an extra step to get back our original Set.
1. Quick Manual Conversion
The simplest approach is to take the array returned by unmarshall and convert it to a Set explicitly:
import {marshall, unmarshall} from '@aws-sdk/util-dynamodb'; test('Marshall and Unmarshall Test', () => { const raw = { 'anArray': new Set([ 'Apple', 'Mango' ]) }; const marshalledResult = marshall(raw); // Unmarshall to get an array, then convert to Set const unmarshalled = unmarshall(marshalledResult); const restoredData = { ...unmarshalled, anArray: new Set(unmarshalled.anArray) }; console.log(restoredData); // { anArray: Set(2) { 'Apple', 'Mango' } } });
2. Reusable Custom Unmarshaller
If you work with Sets often, create a helper function to automatically convert all DynamoDB set types back to JS Sets:
import {marshall, unmarshall} from '@aws-sdk/util-dynamodb'; function unmarshallWithSets(data) { const unmarshalled = unmarshall(data); // Recursively convert arrays from DynamoDB sets to JS Sets const convertToSets = (obj) => { for (const key in obj) { if (Array.isArray(obj[key])) { obj[key] = new Set(obj[key]); } else if (typeof obj[key] === 'object' && obj[key] !== null) { convertToSets(obj[key]); } } return obj; }; return convertToSets(unmarshalled); } test('Marshall and Unmarshall with Custom Handler', () => { const raw = { 'anArray': new Set([ 'Apple', 'Mango' ]) }; const marshalledResult = marshall(raw); const restoredData = unmarshallWithSets(marshalledResult); console.log(restoredData); // { anArray: Set(2) { 'Apple', 'Mango' } } });
3. Update Your SDK Package
If you're getting an empty object instead of an array during unmarshalling, it's likely due to an outdated version of @aws-sdk/util-dynamodb. Update to the latest version to fix this bug:
npm update @aws-sdk/util-dynamodb
Key Takeaways
- Marshalling works out of the box: the SDK converts JS
Setobjects to DynamoDB'sSS/NS/BStypes automatically. - Unmarshalling defaults to arrays, so you need explicit conversion if you want to work with Sets directly.
- Updating your SDK package will resolve unexpected empty object issues caused by old bugs.
内容的提问来源于stack exchange,提问作者kaushalpranav

