Python Lambda 函数解析 DynamoDB 的 JSON 格式

Posted

技术标签:

【中文标题】Python Lambda 函数解析 DynamoDB 的 JSON 格式【英文标题】:Python Lambda Function Parsing DynamoDB's JSON Format 【发布时间】:2016-10-20 14:02:31 【问题描述】:

为 dynamodb 流调用的 Python Lambda 函数具有 DynamoDB 格式的 JSON(包含 JSON 中的数据类型)。我想将 DynamoDB JSON 转换为标准 JSON。 php 和 nodejs 有 Marshaler 可以做到这一点。如果 Python 有类似或其他选项,请告诉我。

DynamoDB_format = `"feas":
    "M": 
        "fea": 
            "L": [
                
                    "M": 
                        "pre": 
                            "N": "1"
                        ,
                        "Li": 
                            "N": "1"
                        ,
                        "Fa": 
                            "N": "0"
                        ,
                        "Mo": 
                            "N": "1"
                        ,
                        "Ti": 
                            "S": "20160618184156529"
                        ,
                        "Fr": 
                            "N": "4088682"
                        
                    
                
                ]
               
        
    
`

【问题讨论】:

【参考方案1】:

更新:现在有一个库:https://pypi.org/project/dynamodb-json/


这是indiangolfer's answer 的改进版本。 虽然@indiangolfer 的解决方案适用于该问题,但此改进版本可能对偶然发现此线程的其他人更有用。

def unmarshal_dynamodb_json(node):
    data = dict()
    data['M'] = node
    return _unmarshal_value(data)


def _unmarshal_value(node):
    if type(node) is not dict:
        return node

    for key, value in node.items():
        # S – String - return string
        # N – Number - return int or float (if includes '.')
        # B – Binary - not handled
        # BOOL – Boolean - return Bool
        # NULL – Null - return None
        # M – Map - return a dict
        # L – List - return a list
        # SS – String Set - not handled
        # NN – Number Set - not handled
        # BB – Binary Set - not handled
        key = key.lower()
        if key == 'bool':
            return value
        if key == 'null':
            return None
        if key == 's':
            return value
        if key == 'n':
            if '.' in str(value):
                return float(value)
            return int(value)
        if key in ['m', 'l']:
            if key == 'm':
                data = 
                for key1, value1 in value.items():
                    if key1.lower() == 'l':
                        data = [_unmarshal_value(n) for n in value1]
                    else:
                        if type(value1) is not dict:
                            return _unmarshal_value(value)
                        data[key1] = _unmarshal_value(value1)
                return data
            data = []
            for item in value:
                data.append(_unmarshal_value(item))
            return data

从以下几个方面进行改进:

处理更多data types,包括以前未正确处理的列表

处理小写和大写键

编辑:修复递归对象错误

【讨论】:

感谢您改进我的回答。太棒了! 问题询问如何将DynamoDB流对象转换为标准JSON。 dynamodb-json 库不这样做,它不输出有效的 JSON。它将接收到的对象转换为 Python 对象,然后用类型等返回原始可怕的 JSON 对象......【参考方案2】:

我在野外找不到任何东西。所以,我决定将 dynamodb json 的 PHP 实现移植到标准 json 中,该标准 json 发布在 here 上。我在处理 DynamoDB 流的 python lambda 函数中对此进行了测试。如果有更好的方法,请告诉我。

(PS:这不是PHP Marshaler的完整移植版)

问题中的 JSON 转换为:

  
   "feas":  
      "fea":[  
           
            "pre":"1",
            "Mo":"1",
            "Ti":"20160618184156529",
            "Fa":"0",
            "Li":"1",
            "Fr":"4088682"
         
      ]
   


def unmarshalJson(node):
    data = 
    data["M"] = node
    return unmarshalValue(data, True)


def unmarshalValue(node, mapAsObject):
    for key, value in node.items():
        if(key == "S" or key == "N"):
            return value
        if(key == "M" or key == "L"):
            if(key == "M"):
                if(mapAsObject):
                    data = 
                    for key1, value1 in value.items():
                        data[key1] = unmarshalValue(value1, mapAsObject)
                    return data
            data = []
            for item in value:
                data.append(unmarshalValue(item, mapAsObject))
            return data

【讨论】:

【参考方案3】:

为了轻松与 DynamoDB JSON 相互转换,我建议使用 boto3 dynamodb 类型的序列化器和反序列化器。

import boto3
from boto3.dynamodb.types import TypeSerializer, TypeDeserializer
ts= TypeSerializer()
td = TypeDeserializer()

data= "id": "5000"
serialized_data= ts.serialize(data)
print(serialized_data)
#'M': 'id': 'S': '5000'
deserialized_data= td.deserialize(serialized_data)
print(deserialized_data)
#'id': '5000'

更多详情check out the boto3.dynamodb.types classes。

【讨论】:

这并不需要一个完整的 JSON 对象,从事物的外观来看,一次只需要一个字段......

以上是关于Python Lambda 函数解析 DynamoDB 的 JSON 格式的主要内容,如果未能解决你的问题,请参考以下文章

新手入门,深入解析 python lambda表达式

Python Lambda 函数解析 DynamoDB 的 JSON 格式

内置函数filter()和匿名函数lambda解析

如何在 Lambda 中使用 python 从 dynamoDB 获取/获取某些列?

Python filter,map,lambda,reduce,列表解析

Python Lambda函数的几种使用方法