1

I have to write a utility function which reads a dynamodb item and returns a flattened version of that record.

Sample Item

const data={
  "node": {
    "S": "someKey"
  },
  "payload": {
    "M": {
      "name": {
        "S": "some_name"
      },
      "phone": {
        "M": {
          "0": {
            "S": "+126526562562"
          },
          "1": {
            "S": "+126512651652"
          }
        }
      },
      "country": {
        "S": "US"
      }
    }
  }
}

Below is the sample utility function .

const utility = (result, field) => {

  const mapping = result[field];
  const { M: data } = mapping;

  const fieldTypes = ['N','S','M'];
  return Object.fromEntries(
    Object
      .keys(data)
      .map((key) => ({ fieldType: Object.keys(data[key]).shift(), key }))
      .filter((o) => fieldTypes.includes(o.fieldType))
      .map((o) => [o.key, data[o.key][o.fieldType]]),
  );
};

console.log(flattenMap(data,'payload'))

This function works fine if there are no maps inside payload. For example, if I remove the phone attribute from dynamodb item , then I get { name: 'some_name', country: 'US' } which is correct but with phone, I get -

{
  name: 'some_name',
  phone: { '0': { S: '+126526562562' }, '1': { S: '+126512651652' } },
  country: 'US'
}

whereas, what I expect is

{
  name: 'some_name',
  phone: { '0':'+126526562562' }, '1': '+126512651652' },
  country: 'US'
}

What more do I need to add here so that I get the expected response even with a nested map inside payload.

1 Answer 1

1

The easy way: use the SDK v3 DynamoDB utilities to handle conversions:

import { convertToNative } from '@aws-sdk/util-dynamodb';
const converted = convertToNative(payload)

If you insist on DIY: use recursion to deal with arbitrary nesting. The utility function's logic should be invoked recursively for every value in the payload that is a DynamoDB "map" such as { S: '+126526562562' }.

Values are DynamoDB "maps" if they are key-value pairs with keys of ['N','S','M']:

if (val.constructor === Object && Object.keys(val).every(k => fieldTypes.includes(k))) {
  // val is a DynamoDB map, call the function recursively on val
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.