Python Lambda Function Parsing DynamoDB's JSON Format Python Lambda Function Parsing DynamoDB's JSON Format json json

Python Lambda Function Parsing DynamoDB's JSON Format


Update: There is a library now: https://pypi.org/project/dynamodb-json/


Here is an improved version of indiangolfer's answer.While @indiangolfer's solution works for the question, this improved version might be more useful for others who stumble upon this thread.

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

It is improved in the following ways:

  • handles more data types, including lists, which were not handled correctly previously

  • handles lowercase and uppercase keys

Edit: fix recursive object bug


I couldn't find anything out in the wild. So, I decided to port the PHP implementation of dynamodb json to standard json that was published here. I tested this in a python lambda function processing DynamoDB stream. If there is a better way to do this, please let me know.

(PS: This is not a complete port of PHP Marshaler)

The JSON in the question gets transformed to:

{     "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


To easily convert to and from the DynamoDB JSON I recommend using the boto3 dynamodb types serializer and deserializer.

import boto3from boto3.dynamodb.types import TypeSerializer, TypeDeserializerts= 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'}

For more details check out the boto3.dynamodb.types classes.