在 AWS Lambda 中将 DynamoDB 数据格式化为普通的 JSON

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/32712675/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 18:03:27  来源:igfitidea点击:

Formatting DynamoDB data to normal JSON in AWS Lambda

jsonamazon-web-servicesamazon-dynamodbaws-lambda

提问by Chaitanya

I'm using AWS Lambdato scan data from a DynamoDBtable. This is what I get in return:

我正在使用AWS Lambda扫描DynamoDB表中的数据。这是我得到的回报:

{
  "videos": [
    {
      "file": {
        "S": "file1.mp4"
      },
      "id": {
        "S": "1"
      },
      "canvas": {
        "S": "This is Canvas1"
      }
    },
    {
      "file": {
        "S": "main.mp4"
      },
      "id": {
        "S": "0"
      },
      "canvas": {
        "S": "this is a canvas"
      }
    }
  ]
}

My front-end application is using Ember Data Rest Adapterwhich does not accepts such response. Is there any way I can get normal JSON format? There is this NPM module called dynamodb-marshalerto convert DynamoDB data to normal JSON. I'm looking for a native solutionif possible.

我的前端应用程序正在使用不接受此类响应的Ember Data Rest Adapter。有什么办法可以获得正常的 JSON 格式吗?有一个 NPM 模块被调用dynamodb-marshaler来将 DynamoDB 数据转换为普通的 JSON。如果可能,我正在寻找本机解决方案

采纳答案by Vasily Sochinsky

AWS JavaScript SDK was recently updated with Document Client which does exactly what you need. Check the announce and usage examples here: http://blogs.aws.amazon.com/javascript/post/Tx1OVH5LUZAFC6T/Announcing-the-Amazon-DynamoDB-Document-Client-in-the-AWS-SDK-for-JavaScript

AWS JavaScript SDK 最近更新了 Document Client,它完全符合您的需求。在此处查看公告和使用示例:http: //blogs.aws.amazon.com/javascript/post/Tx1OVH5LUZAFC6T/Announcing-the-Amazon-DynamoDB-Document-Client-in-the-AWS-SDK-for-JavaScript

回答by David Rissato Cruz

Actually you should use the unmarshallfunction from AWSJavaScriptSDK:

实际上,您应该使用AWSJavaScriptSDK 中unmarshall函数:

const AWS = require("aws-sdk");

exports.handler = function( event, context, callback ) {
  const newImages = event.Records.map(
        (record) => AWS.DynamoDB.Converter.unmarshall(record.dynamodb.NewImage)
  );
  console.log('Converted records', newImages);
  callback(null, `Success`);
}

回答by dolcalmi

I know is a bit old but I had the same problem processing stream data from dynamoDB in node js lambda function. I used the proposed by @churro

我知道这有点旧,但我在 node js lambda 函数中处理来自 dynamoDB 的流数据时遇到了同样的问题。我使用了@churro 提出的

import sdk and output converter

导入sdk和输出转换器

var AWS = require("aws-sdk");
var parse = AWS.DynamoDB.Converter.output;

use the parse function with a small hack

使用 parse 函数和一个小技巧

exports.handler = function( event, context, callback ) {
  var docClient = new AWS.DynamoDB.DocumentClient();
  event.Records.forEach((record) => {
        console.log(record.eventID);
        console.log(record.eventName);
        console.log('DynamoDB Record:', parse({ "M": record.dynamodb.NewImage }));
    });
  callback(null, `Successfully processed ${event.Records.length} records.`);
}

Hope it helps

希望能帮助到你

回答by igorzg

Here you can find gist which does that:

在这里你可以找到这样做的要点:

function mapper(data) {

let S = "S";
let SS = "SS";
let NN = "NN";
let NS = "NS";
let BS = "BS";
let BB = "BB";
let N = "N";
let BOOL = "BOOL";
let NULL = "NULL";
let M = "M";
let L = "L";

if (isObject(data)) {
    let keys = Object.keys(data);
    while (keys.length) {
        let key = keys.shift();
        let types = data[key];

        if (isObject(types) && types.hasOwnProperty(S)) {
            data[key] = types[S];
        } else if (isObject(types) && types.hasOwnProperty(N)) {
            data[key] = parseFloat(types[N]);
        } else if (isObject(types) && types.hasOwnProperty(BOOL)) {
            data[key] = types[BOOL];
        } else if (isObject(types) && types.hasOwnProperty(NULL)) {
            data[key] = null;
        } else if (isObject(types) && types.hasOwnProperty(M)) {
            data[key] = mapper(types[M]);
        } else if (isObject(types) && types.hasOwnProperty(L)) {
            data[key] = mapper(types[L]);
        } else if (isObject(types) && types.hasOwnProperty(SS)) {
            data[key] = types[SS];
        } else if (isObject(types) && types.hasOwnProperty(NN)) {
            data[key] = types[NN];
        } else if (isObject(types) && types.hasOwnProperty(BB)) {
            data[key] = types[BB];
        } else if (isObject(types) && types.hasOwnProperty(NS)) {
            data[key] = types[NS];
        } else if (isObject(types) && types.hasOwnProperty(BS)) {
            data[key] = types[BS];
        }
    }
}


return data;

function isObject(value) {
    return typeof value === "object" && value !== null;
}

}

}

https://gist.github.com/igorzg/c80c0de4ad5c4028cb26cfec415cc600

https://gist.github.com/igorzg/c80c0de4ad5c4028cb26cfec415cc600

回答by forzagreen

from boto3.dynamodb.types import TypeDeserializer, TypeSerializer

def from_dynamodb_to_json(item):
    d = TypeDeserializer()
    return {k: d.deserialize(value=v) for k, v in item.items()}

## Usage:
from_dynamodb_to_json({
    "Day": {"S": "Monday"},
    "mylist": {"L": [{"S": "Cookies"}, {"S": "Coffee"}, {"N": "3.14159"}]}
})
# {'Day': 'Monday', 'mylist': ['Cookies', 'Coffee', Decimal('3.14159')]}

===== OUTDATED: =====

===== 过时:=====

In python use this custom code:

在 python 中使用这个自定义代码:

DYANMODB_TYPES = {
    "S": lambda value: str(value),
    "N": lambda value: float(value),
    "B": lambda value: value.encode(),
    "NULL": lambda value: bool(value),
    "BOOL": lambda value: bool(value),
    "SS": lambda value: list(map(str, value)),
    "NS": lambda value: list(map(float, value)),
    "BS": lambda value: [e.encode() for e in value],
    "M": lambda value: from_dynamodb_to_json(value),
    "L": lambda value: [_convert_type(e) for e in value]
}

def _convert_type(sub_obj):
    attribute_type = list(sub_obj.keys())[0]
    raw_value = sub_obj[attribute_type]
    return DYANMODB_TYPES.get(attribute_type)(raw_value)

def from_dynamodb_to_json(item):
    converted_obj = {}
    for key in item.keys():
        converted_obj[key] = _convert_type(item[key])
    return converted_obj

## Usage:
from_dynamodb_to_json({
    "Day": {"S": "Monday"},
    "mylist": {"L": [{"S": "Cookies"}, {"S": "Coffee"}, {"N": "3.14159"}]}
})
# {'Day': 'Monday', 'mylist': ['Cookies', 'Coffee', 3.14159]}

回答by Chandan Kumar

If you are using python in the lambda you can utilise the dynamodb-json library.

如果您在 lambda 中使用 python,则可以使用 dynamodb-json 库。

Install library

安装库

pip install dynamodb-json

and use the below snippet

并使用以下代码段

from dynamodb_json import json_util as util

def marshall(regular_json):
    dynamodb_json = util.dumps(reular_json)

def unmarshall(dynamodb_json):
    regular_json = util.loads(dynamodb_json)

Reference https://pypi.org/project/dynamodb-json/

参考 https://pypi.org/project/dynamodb-json/

回答by James

I think it's just a custom transformation exercise for each app. A simple conversion from DynamoDB's item format to you application format might look like this:

我认为这只是每个应用程序的自定义转换练习。从 DynamoDB 的项目格式到您的应用程序格式的简单转换可能如下所示:

var response = {...} // your response from DynamoDB
var formattedObjects = response.videos.map(function(video) {
    return {
        "file": video.file.S,
        "id": video.id.S,
        "canvas": video.canvas.S
    };
});

If you want to build a generic system for this, you would have to handle DynamoDB's various AttributeValue types. A function like the one below would do the job, but I've left out the hard work of handling most of DynamoDB's more complex attribute value types:

如果要为此构建通用系统,则必须处理 DynamoDB 的各种AttributeValue 类型。像下面这样的函数可以完成这项工作,但我忽略了处理大多数 DynamoDB 更复杂的属性值类型的艰巨工作:

function dynamoItemToPlainObj(dynamoItem) {
    var plainObj = {};
    for (var attributeName in dynamoItem) {
        var attribute = dynamoItem[attributeName];
        var attributeValue;
        for (var itemType in attribute) {
            switch (itemType) {
            case "S":
                attributeValue = attribute.S.toString();
                break;
            case "N":
                attributeValue = Number(attribute.N);
                break;
                // more attribute types...
            default:
                attributeValue = attribute[itemType].toString();
                break;
            }
        }
        plainObj[attributeName] = attributeValue;
    }
    return plainObj;
}    
var formattedObjects = response.videos.map(dynamoItemToPlainObj);

回答by Beka

If you need online editor try this

如果你需要在线编辑器试试这个

https://2json.net/dynamo

https://2json.net/dynamo