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

时间:2015-09-22 08:57:28

标签: json amazon-web-services amazon-dynamodb aws-lambda

我使用 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"
      }
    }
  ]
}

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

8 个答案:

答案 0 :(得分:21)

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

导入sdk和输出转换器

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

使用带有小黑客的解析功能

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.`);
}

希望有所帮助

答案 1 :(得分:19)

实际上您应该使用AWSJavaScriptSDK中的import matplotlib.pyplot as plt import matplotlib.gridspec as gridspec import seaborn as sns; sns.set() import SeabornFig2Grid as sfg iris = sns.load_dataset("iris") tips = sns.load_dataset("tips") # An lmplot g0 = sns.lmplot(x="total_bill", y="tip", hue="smoker", data=tips, palette=dict(Yes="g", No="m")) # A PairGrid g1 = sns.PairGrid(iris, hue="species") g1.map(plt.scatter, s=5) # A FacetGrid g2 = sns.FacetGrid(tips, col="time", hue="smoker") g2.map(plt.scatter, "total_bill", "tip", edgecolor="w") # A JointGrid g3 = sns.jointplot("sepal_width", "petal_length", data=iris, kind="kde", space=0, color="g") fig = plt.figure(figsize=(13,8)) gs = gridspec.GridSpec(2, 2) mg0 = sfg.SeabornFig2Grid(g0, fig, gs[0]) mg1 = sfg.SeabornFig2Grid(g1, fig, gs[1]) mg2 = sfg.SeabornFig2Grid(g2, fig, gs[3]) mg3 = sfg.SeabornFig2Grid(g3, fig, gs[2]) gs.tight_layout(fig) #gs.update(top=0.7) plt.show() 功能:

unmarshall

答案 2 :(得分:14)

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

答案 3 :(得分:1)

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

安装库

pip install dynamodb-json

并使用以下代码段

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)

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

答案 4 :(得分:0)

  • JavaScript :AWS开发工具包提供了unmarshall函数

  • 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]}

答案 5 :(得分:0)

我在这里尝试了几种解决方案,但没有一个适用于多级数据,例如如果它包含地图列表,例如

{
  "item1": {
    "M": {
      "sub-item1": {
        "L": [
          {
            "M": {
              "sub-item1-list-map": {
                "S": "value"

下面改编自@igorzg 的回答,修复了这个问题。

示例用法:

dynamodb.getItem({...}, function(err, data) {
  if (!err && data && data.Item) {
    var converted = ddb_to_json(data.Item);

这是转换函数:

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

  if(isObject(data))
    return convert_ddb({M:data});

  function convert_ddb(ddbData) {
    if (isObject(ddbData) && ddbData.hasOwnProperty('S'))
      return ddbData.S;
    if (isObject(ddbData) && ddbData.hasOwnProperty('N'))
      return parseFloat(ddbData.N);
    if (isObject(ddbData) && ddbData.hasOwnProperty('BOOL'))
      return ddbData.BOOL;
    if (isObject(ddbData) && ddbData.hasOwnProperty('NULL'))
      return null;
    if (isObject(ddbData) && ddbData.hasOwnProperty('M')) {
      var x = {};
      for(var k in ddbData.M)
        x[k] = convert_ddb(ddbData.M[k])
      return x;
    }
    if (isObject(ddbData) && ddbData.hasOwnProperty('L'))
      return ddbData.L.map(x => convert_ddb(x));
    if (isObject(ddbData) && ddbData.hasOwnProperty('SS'))
      return ddbData.SS;
    if (isObject(ddbData) && ddbData.hasOwnProperty('NN'))
      return ddbData.NN;
    if (isObject(ddbData) && ddbData.hasOwnProperty('BB'))
      return ddbData.BB;
    if (isObject(ddbData) && ddbData.hasOwnProperty('NS'))
      return ddbData.NS;
    if (isObject(ddbData) && ddbData.hasOwnProperty('BS'))
      return ddbData.BS;

    return data;
  }

  return data;
}

答案 6 :(得分:-1)

我认为这只是每个应用的自定义转换练习。从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
    };
});

如果您想为此构建通用系统,则必须处理DynamoDB的各种AttributeValue types。像下面这样的函数可以完成这项工作,但我遗漏了处理大多数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);

答案 7 :(得分:-1)

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

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