Skip to content

Instantly share code, notes, and snippets.

@JamieCressey
Created April 24, 2016 20:56
Show Gist options
  • Star 18 You must be signed in to star a gist
  • Fork 8 You must be signed in to fork a gist
  • Save JamieCressey/a3a75a397db092d7a70bbe876a6fb817 to your computer and use it in GitHub Desktop.
Save JamieCressey/a3a75a397db092d7a70bbe876a6fb817 to your computer and use it in GitHub Desktop.
Coverts a standard Python dictionary to a Boto3 DynamoDB item
def dict_to_item(raw):
if type(raw) is dict:
resp = {}
for k,v in raw.iteritems():
if type(v) is str:
resp[k] = {
'S': v
}
elif type(v) is int:
resp[k] = {
'I': str(v)
}
elif type(v) is dict:
resp[k] = {
'M': dict_to_item(v)
}
elif type(v) is list:
resp[k] = []
for i in v:
resp[k].append(dict_to_item(i))
return resp
elif type(raw) is str:
return {
'S': raw
}
elif type(raw) is int:
return {
'I': str(raw)
}
@pavelanni
Copy link

Very helpful, thanks!

@franchb
Copy link

franchb commented Nov 30, 2017

Thank you!

@anztrax
Copy link

anztrax commented Dec 21, 2017

Very helpful, thanks!

@tjdaley
Copy link

tjdaley commented Jan 6, 2018

Thank you for adding time back to my life!!

@odedniv
Copy link

odedniv commented Mar 13, 2018

How about:

def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
            'M': {
                k: dict_to_item(v)
                for k, v in raw.items()
            }
        }
    elif isinstance(raw, list):
        return {
            'L': [dict_to_item(v) for v in raw]
        }
    elif isinstance(raw, str):
        return {'S': raw}
    elif isinstance(raw, int):
        return {'N': str(raw)}

@ahbrown1
Copy link

@odedniv ; much better. the original gist was on the write track, but was missing a few edge cases.

@awkwords
Copy link

awkwords commented Oct 1, 2018

@odedniv thanks

@renjinsk
Copy link

renjinsk commented Aug 6, 2019

Well, i had some errors with the second code, so i had to make some minor tweaks..

def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
            'M': {
                key: dict_to_item(value)
                for key, value in raw.items()
            }
        }
    elif isinstance(raw, list):
        return {
            'L': [dict_to_item(value) for value in raw]
        }
    elif isinstance(raw, str) or isinstance(raw, unicode):
        return {'S': raw}
    elif isinstance(raw, int):
        return {'N': str(raw)}
    elif raw is None:
        return {'NULL': True}

@akshowhini
Copy link

akshowhini commented Aug 11, 2019

Improved the above code

  1. isintance accepts tuple to use in or conditions
  2. Handled float, bool, bytes types
def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
            'M': {
                key: dict_to_item(value)
                for key, value in raw.items()
            }
        }
    elif isinstance(raw, list):
        return {
            'L': [dict_to_item(value) for value in raw]
        }
    elif isinstance(raw, (str, unicode)):
        return {'S': raw}
    elif isinstance(raw, (int, float)):
        return {'N': str(raw)}
    elif isinstance(raw, bool):
        return {'BOOL': raw}
    elif isinstance(raw, bytes):
        return {'B': raw}
    elif raw is None:
        return {'NULL': True}

@adbumi
Copy link

adbumi commented Sep 17, 2019

When checking with isinstance() we should take care for the sequence. First check for 'bool' and only then for 'int' and 'float'
because isinstance(raw, (int, float)) returns True for boolen values:

def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
            'M': {
                key: dict_to_item(value)
                for key, value in raw.items()
            }
        }
    elif isinstance(raw, list):
        return {
            'L': [dict_to_item(value) for value in raw]
        }
    elif isinstance(raw, (str, unicode)):
        return {'S': raw}
    elif isinstance(raw, bool):
        return {'BOOL', raw}
    elif isinstance(raw, (int, float)):
        return {'N': str(raw)}
    elif isinstance(raw, bytes):
        return {'B', raw}
    elif raw is None:
        return {'NULL': True}

@barrypearseburke
Copy link

@akshowhini
Can you edit your post. for bool, you have a comma instead of a colan.
But thanks all, i was thinking of how to covert my dict to dynamoDB and didnt want to have to write this :)

@fakabbir
Copy link

Thanks, I wasn't able to insert the values in this format:

boto3.version : '1.12.43'
Python 3.6.10 |Anaconda, Inc.| (default, Mar 23 2020, 17:58:33) [MSC v.1916 64 bit (AMD64)] on win32

{'M': {'Row No': {'S': '1'},
 'Activity': {'S': 'Playing'},
 'Game \n Indoor': {'S': 'Football'},
 'TIME_STAMP': {'S': '20200426-155655-8555'},
 'ID': {'S': '5305968026208007210'}
}}

or

{'Row No': {'S': '1'},
 'Activity': {'S': 'Playing'},
 'Game \n Indoor': {'S': 'Football'},
 'TIME_STAMP': {'S': '20200426-155655-8555'},
 'ID': {'S': '5305968026208007210'}
}

So I made another tweak to get the work done

#To Correct The Keys, If Automated Extraction From Forms
def get_corrected_key(key):
    removal_list = [' ', '\t', '\n']
    for s in removal_list:
        key = key.replace(s, '')
    return key

def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
                get_corrected_key(key): dict_to_item(value)
                for key, value in raw.items()
        }
    elif isinstance(raw, list):
        return {
            [dict_to_item(value) for value in raw]
        }
    elif isinstance(raw, str):
        # Empty Strings are not a valid entry 
        if len(raw) ==0:
            return '-'
        return raw
    elif isinstance(raw, bool):
        return raw
    elif isinstance(raw, (int, float)):
        return str(raw)
    elif isinstance(raw, bytes):
        return raw
    elif raw is None:
        return True

table_work.put_item(
    Item=dict_to_item(item))

@jesshart
Copy link

jesshart commented Jan 27, 2021

I wanted to use this with a pandas DataFrame object so I used it like this:

import pandas as pd

def preprocess_df(df):
    df.index = df.index.astype('str')
    df_dict = df.to_dict()
    return df_dict

def dict_to_item(raw):
    if isinstance(raw, dict):
        return {
            'M': {
                key: dict_to_item(value)
                for key, value in raw.items()
            }
        }
    elif isinstance(raw, list):
        return {
            'L': [dict_to_item(value) for value in raw]
        }
    elif isinstance(raw, (str)):
        return {'S': raw}
    elif isinstance(raw, bool):
        return {'BOOL': raw}
    elif isinstance(raw, (int, float)):
        return {'N': str(raw)}
    elif isinstance(raw, bytes):
        return {'B', raw}
    elif raw is None:
        return {'NULL': True}

def df_to_aws_dict(df):
    aws_dict = dict_to_item(preprocess_df(df))
    return aws_dict

@yousefcodes
Copy link

from boto3.dynamodb.types import TypeSerializer
serializer = TypeSerializer()
item = {"foo": "bar"}
dyn_item = {key: serializer.serialize(value) for key, value in item.items()}

@jakariadev
Copy link

from boto3.dynamodb.types import TypeSerializer
serializer = TypeSerializer()
item = {"foo": "bar"}
dyn_item = {key: serializer.serialize(value) for key, value in item.items()}

This really works for me. Thanks a lot, @yousefcodes . I was Stack on it for 1 day. Much Appreciated. Is it possible to do as this works in Update items?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment