AWS Lambda
DynamoDB
JSON serialization
Python
Decimal error

Object of type 'Decimal' is not JSON serializable AWS Lambda - DynamoDB

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

When working with AWS Lambda in conjunction with DynamoDB, a common problem developers encounter is related to the serialization of data types, specifically when dealing with the Decimal type. DynamoDB often uses Decimal to represent numbers as it offers arbitrary precision, which is beneficial for accurately handling large numbers or high-precision monetary values. However, this data type isn't natively supported by JSON serialization, leading to errors and headaches during development.

Understanding the Error

When you attempt to serialize a Python object containing a Decimal type to JSON, you might encounter the error:

 
TypeError: Object of type 'Decimal' is not JSON serializable

This occurs because the default Python json module does not understand how to convert Decimal to a format that can be represented in JSON, which typically only supports basic numeric types like int and float.

Example Scenario

Consider the following excerpt from a Python Lambda function interacting with DynamoDB:

python
1import json
2import boto3
3from decimal import Decimal
4
5def lambda_handler(event, context):
6    dynamodb = boto3.resource('dynamodb')
7    table = dynamodb.Table('YourTableName')
8    
9    # Sample item with a Decimal type
10    item = {
11        'id': '123',
12        'balance': Decimal('100.75')  # Decimal type
13    }
14
15    table.put_item(Item=item)
16
17    # Attempting to return this item will cause an error
18    return {
19        'statusCode': 200,
20        'body': json.dumps(item)
21    }

In this scenario, the Decimal type for the balance field is not JSON serializable, causing the Lambda to fail when attempting to return the item as a response.

Solutions to the Problem

Custom Encoder

One approach to resolve this issue is to create a custom JSON encoder. Here's how you can implement it:

python
1class DecimalEncoder(json.JSONEncoder):
2    def default(self, obj):
3        if isinstance(obj, Decimal):
4            # Convert Decimal to float
5            return float(obj)
6        return super(DecimalEncoder, self).default(obj)
7
8def lambda_handler(event, context):
9    dynamodb = boto3.resource('dynamodb')
10    table = dynamodb.Table('YourTableName')
11    
12    item = {
13        'id': '123',
14        'balance': Decimal('100.75')
15    }
16
17    table.put_item(Item=item)
18
19    return {
20        'statusCode': 200,
21        'body': json.dumps(item, cls=DecimalEncoder)
22    }

This custom encoder checks if the object is of type Decimal and converts it to a float before serialization.

Using Decimal to Float Conversion

Another straightforward method is converting Decimal to float directly before serialization:

python
1def decimal_default(obj):
2    if isinstance(obj, Decimal):
3        return float(obj)
4    raise TypeError
5
6def lambda_handler(event, context):
7    dynamodb = boto3.resource('dynamodb')
8    table = dynamodb.Table('YourTableName')
9    
10    item = {
11        'id': '123',
12        'balance': Decimal('100.75')
13    }
14
15    table.put_item(Item=item)
16
17    # Use the default parameter in json.dumps to provide our conversion function
18    return {
19        'statusCode': 200,
20        'body': json.dumps(item, default=decimal_default)
21    }

Key Points Summary

AspectDescription
Error SourceOccurs when attempting to serialize Decimal type using Python's default json module.
Typical ScenarioOften seen in AWS Lambda functions when interacting with DynamoDB, which uses Decimal for numeric attributes.
Common SolutionImplement a custom JSONEncoder to handle Decimal types.
Alternative SolutionConvert Decimal to float before serialization.
Consideration in Solution ChoiceConverting to float can introduce precision issues with high precision decimals.

Additional Tips

  • Precision Consideration: When converting Decimal to float, be cautious as this may lead to loss of precision if the Decimal value has a high number of decimal places.
  • Use Libraries: Consider using libraries like simplejson which provide enhanced support for more complex data types.
  • DynamoDB Client Configuration: Boto3 automatically converts Decimal to Python float if you specify the correct parameter when calling Table resource methods, simplifying your task further.

Understanding and mitigating serialization issues in your AWS Lambda functions ensures robustness and reliability when interacting with AWS services. By considering these solutions and adopting best practices, you can efficiently handle serialization of Decimal types and improve the efficiency of your Lambda functions.


Course illustration
Course illustration

All Rights Reserved.