Typeerror: Object Of Type Decimal Is Not Json Serializable

5 min read

TypeError: Object of Type Decimal Is Not JSON Serializable – Causes and Solutions

When working with Python’s json module to serialize data structures, developers often encounter the error: “TypeError: object of type Decimal is not JSON serializable.Here's the thing — ” This error typically occurs when attempting to convert a Decimal object (from Python’s decimal module) into a JSON-formatted string using json. Also, dumps(). Practically speaking, while JSON supports basic data types like strings, numbers, and booleans, it does not natively handle Python’s Decimal type. This article explains the root cause of this error, provides practical solutions, and outlines best practices for handling Decimal objects in JSON serialization.


Understanding the Error

What Triggers the Error?

The error arises when Python’s json module encounters a Decimal object during serialization. Here’s an example that reproduces the issue:

import json  
from decimal import Decimal  

data = {"price": Decimal("19.99")}  
json_str = json.dumps(data)  

Output:

TypeError: object of type Decimal is not JSON serializable  

Why Does This Happen?

The json module in Python only supports the following data types for serialization:

  • Strings
  • Numbers (integers and floats)
  • Booleans
  • Lists and tuples
  • Dictionaries
  • None

The Decimal type is not part of this list. Unlike float or int, Decimal is a specialized class designed for high-precision arithmetic, often used in financial or scientific applications. Since JSON’s specification does not define a Decimal type, the json module raises an error when it encounters one.


Why Use Decimal Instead of Float?

Before diving into solutions, it’s important to understand why developers opt for Decimal in the first place:

  1. Precision: Floating-point numbers (e.g., float) can introduce rounding errors in calculations. To give you an idea, 0.1 + 0.2 in Python equals 0.30000000000000004 instead of 0.3.
  2. Control Over Rounding: The decimal module allows precise control over rounding modes and significant digits.
  3. Financial Calculations: Monetary values often require exact decimal representation to avoid discrepancies in billing or accounting systems.

Because of these advantages, Decimal is preferred in scenarios where accuracy is critical. That said, this comes at the cost of compatibility with JSON, which is why the error occurs.


Solutions to Fix the Error

Solution 1: Convert Decimal to Float

The simplest fix is to convert Decimal objects to float before serialization:

import json  
from decimal import Decimal  

data = {"price": Decimal("19.99")}  
json_str = json.dumps({"price": float(data["price"])})  
print(json_str)  

Output:

{"price": 19.99}  

Caveat: Converting to float may reintroduce rounding errors. Use this method only when precision loss is acceptable (e.g., displaying values to users).


Solution 2: Use a Custom JSON Encoder

Python’s json.dumps() allows custom encoders via the default parameter. Create a function to handle Decimal objects:

import json  
from decimal import Decimal  

def decimal_to_float(obj):  
    if isinstance(obj, Decimal):  
        return float(obj)  
    raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")  

data = {"price": Decimal("19.99")}  
json_str = json.dumps(data, default=decimal_to_float)  
print(json_str)  

This approach ensures Decimal objects are converted to float during serialization.


Solution 3: Serialize Decimals as Strings

If precision is critical, serialize Decimal objects as strings:

import json  
from decimal import Decimal  

data = {"price": Decimal("19.99")}  
json_str = json.dumps({"price": str(data["price"])})  
print(json_str)  

Output:

{"price": "19.99"}

### Choosing the Right Strategy  

The three approaches outlined above each address a different aspect of the problem, so the most appropriate one depends on the specific requirements of your project. Below is a quick decision guide:

| Goal | Recommended Approach |
|------|-----------------------|
| **Maximum speed** – you are serialising very large datasets and can tolerate occasional rounding loss. | Convert directly to `float` (`Solution 1`). |
| **Accuracy with minimal code changes** – you already have a custom encoder pipeline and want to keep the conversion logic isolated. | Use a custom `default` function (`Solution 2`). In practice, |
| **Exact decimal representation in the payload** – e. g., financial ledgers where every cent must match the source. | Serialize as strings (`Solution 3`) or store the original `Decimal` objects in a separate non‑JSON field while keeping the JSON clean. 

And yeah — that's actually more nuanced than it sounds.

When performance becomes a bottleneck, consider higher‑level libraries such as **`orjson`** or **`ujson`**, which offer native support for `decimal.Day to day, decimal` and often bypass the JSON spec altogether. These libraries can handle the conversion internally without extra Python overhead, giving you both precision and speed.

---

#### When to Keep `Decimal` in the Database  

If your application stores monetary values in a relational database, it is common practice to keep them as exact types (e.g., `DECIMAL(10,2)`) rather than translating them to floating‑point numbers at all times. Because of that, this eliminates the need for any serialization workaround during read operations. For write‑side workflows, however, you may still rely on `Decimal` for calculations, converting back to `float` only when interfacing with external APIs that mandate IEEE‑754 compliance.

---

#### A Balanced Workflow Example  

```python
import json
from decimal import Decimal

# Core data structure
record = {
    "account_id": "ACC‑12345",
    "balance": Decimal("1523.4567"),
    "last_trade": Decimal("12.34")
}

# Preference: keep balance as string for exactness in JSON
def serialize_record(record):
    return json.dumps(
        record,
        default=lambda o: str(o) if isinstance(o, Decimal) else o
    )

print(serialize_record(record))
# Output: {"account_id":"ACC-12345","balance":"1523.4567","last_trade":"12.34"}

This pattern lets you retain full precision throughout the entire pipeline—no hidden rounding occurs until you deliberately cast to float for UI rendering or third‑party calls Not complicated — just consistent..


Conclusion

Choosing between float, custom encoders, or string serialisation hinges on how much precision your domain demands versus the constraints of your ecosystem. On top of that, for everyday web services where visual fidelity outweighs exact accounting, converting to float offers the simplest path. Also, developers building high‑stakes financial systems should prefer the string‑based strategy or an encoding layer that guarantees immutable decimal representation. Worth adding: by evaluating these options against your performance, reliability, and regulatory requirements, you can select the method that best aligns with the overall architecture of your application. When all is said and done, the goal remains clear: make sure the numbers that travel from one system to another are accurate, consistent, and free from unexpected artifacts introduced by the JSON specification itself.

Newly Live

Freshly Written

Parallel Topics

On a Similar Note

Thank you for reading about Typeerror: Object Of Type Decimal Is Not Json Serializable. We hope the information has been useful. Feel free to contact us if you have any questions. See you next time — don't forget to bookmark!
⌂ Back to Home