Handling Non-Serializable Objects in JSON

The Right Way to Serialize Python Objects with Complex Attributes

Introduction

Serialization is the process of converting a Python object into a format that can be stored or transmitted, such as JSON. The json module in Python makes this task easy, but it comes with a limitation—only basic data types like strings, numbers, lists, and dictionaries are directly supported. When your object contains non-serializable attributes such as datetime objects, file handles, or custom classes, using json.dumps() will raise a TypeError.

This challenge is common in real-world applications, especially in web development, logging, and data storage. To overcome this, Python allows you to take control of how these special attributes are converted into JSON-friendly formats.

Master Python: 600+ Real Coding Interview Questions
Master Python: 600+ Real Coding Interview Questions

The Core Issue: Why TypeError Happens

JSON, as a data-interchange format, was designed to be simple and universal. It doesn’t natively understand Python-specific objects like datetime or Decimal. For example:

import json  
from datetime import datetime  

data = {"time": datetime.now()}  
print(json.dumps(data))  # Raises TypeError

Here, the datetime object cannot be directly represented in JSON. JSON only knows how to handle primitive types like strings, integers, floats, booleans, arrays, and key-value mappings. Anything outside of this set must first be converted into one of these supported types.

Machine Learning & Data Science 600+ Real Interview Questions
Machine Learning & Data Science 600 Real Interview Questions

The Step You Should Take: Use a Custom Encoder or default Parameter

The solution lies in teaching json.dumps() how to handle unsupported objects. This can be done by:

  1. Using the default parameter
    The default parameter in json.dumps() accepts a function that tells JSON how to handle non-serializable objects. For example: import json from datetime import datetime def custom_serializer(obj): if isinstance(obj, datetime): return obj.isoformat() raise TypeError(f"Type {type(obj)} not serializable") data = {"time": datetime.now()} print(json.dumps(data, default=custom_serializer)) Here, the datetime object is converted into an ISO 8601 string before being serialized.
  2. Subclassing JSONEncoder
    Another approach is to extend Python’s built-in JSONEncoder class and override its default method: import json from datetime import datetime class CustomEncoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, datetime): return obj.isoformat() return super().default(obj) data = {"time": datetime.now()} print(json.dumps(data, cls=CustomEncoder)) This approach is cleaner when you need to handle multiple object types consistently.

Both methods give you control over how special Python objects are transformed into JSON-supported values.

Master LLM and Gen AI: 600+ Real Interview Questions
Master LLM and Gen AI: 600+ Real Interview Questions

Conclusion

When working with Python objects that include attributes not directly serializable to JSON, a simple call to json.dumps() will not work and will raise a TypeError. The essential step is to provide custom serialization logic—either through the default parameter or by subclassing JSONEncoder. This ensures that unsupported objects, like datetime, are first converted into strings or other supported formats before being serialized.

By taking this step, you make your Python objects compatible with JSON, enabling smooth data exchange in APIs, file storage, and communication across platforms. Ultimately, this approach ensures flexibility, clarity, and reliability in handling real-world data that often extends beyond simple types.


Leave a Reply