How to Resolve "TypeError: Object of type bytes is not JSON serializable" in Python
The TypeError: Object of type bytes is not JSON serializable
is a common Python error encountered when attempting to serialize (convert to JSON format) data containing bytes
objects. The standard JSON format doesn't directly support raw byte sequences.
This guide explains the cause of this error and provides several effective solutions.
Understanding the Error: JSON Doesn't Support Raw Bytes
JSON (JavaScript Object Notation) is a text-based data format. While Python's json
module can serialize many standard Python types (like dictionaries, lists, strings, numbers, booleans, and None
), it doesn't inherently know how to represent raw bytes
objects as a JSON string.
import json
my_bytes = 'tutorialreference.com'.encode('utf-8') # Creates a bytes object
# This line causes the error:
# json_str = json.dumps({'message': my_bytes})
# TypeError: Object of type bytes is not JSON serializable
Solution 1: Decode Bytes to String Before Serialization (Recommended)
The most straightforward and often the best solution is to decode the bytes
object into a string before passing it to json.dumps()
. Since JSON natively supports strings, this works seamlessly.
import json
my_bytes = 'tutorialreference.com'.encode('utf-8')
# Decode the bytes object to a string using UTF-8
decoded_string = my_bytes.decode('utf-8')
json_str = json.dumps({'message': decoded_string})
print(json_str) # Output: {"message": "tutorialreference.com"}
print(type(json_str)) # Output: <class 'str'>
my_bytes.decode('utf-8')
converts the bytes back into a regular Python string using the specified encoding (UTF-8 is common and often the default).- The resulting string is then easily serialized by
json.dumps()
.
Solution 2: Create a Custom JSON Encoder
For more complex scenarios or when you frequently need to handle bytes serialization, you can create a custom JSONEncoder
subclass:
import json
class BytesEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, bytes):
return obj.decode('utf-8') # Decode bytes to string
# Let the base class default method raise the TypeError for other types
return super().default(obj)
my_bytes = 'hello world'.encode('utf-8')
# Use the custom encoder via the 'cls' argument
json_str = json.dumps({'message': my_bytes}, cls=BytesEncoder)
print(json_str) # Output: {"message": "hello world"}
print(type(json_str)) # Output: <class 'str'>
- We inherit from
json.JSONEncoder
. - The
default()
method is overridden. It checks if the object (obj
) is an instance ofbytes
. - If it is bytes, we decode it to a string.
- If it's not bytes, we call the parent class's
default()
method (super().default(obj)
) to handle standard types or raise theTypeError
for other unsupported types. - We pass our custom
BytesEncoder
class to thecls
argument ofjson.dumps()
.
Solution 3: Use the default
Argument in json.dumps()
A simpler alternative to a full custom class is to provide a function to the default
argument of json.dumps()
. This function will be called for objects that the standard encoder doesn't recognize:
import json
my_bytes = 'hello world'.encode('utf-8')
def json_serializer(obj):
if isinstance(obj, bytes):
return obj.decode('utf-8') # Decode bytes
# For other types, you might raise an error or return a default representation
# If you just return obj here, the default encoder will try again,
# potentially leading back to the original TypeError if it's still unsupported.
# It's often better to raise a TypeError here for clarity.
raise TypeError(f"Object of type {type(obj).__name__} is not JSON serializable")
# Use the custom serializer function via the 'default' argument
json_str = json.dumps({'message': my_bytes}, default=json_serializer)
print(json_str) # Output: {"message": "hello world"}
print(type(json_str)) # Output: <class 'str'>
- The
json_serializer
function checks if the object isbytes
and decodes it. - Crucially, if the object isn't
bytes
, the function should ideally raise aTypeError
itself, or return a valid JSON-serializable representation if appropriate for other custom types you might want to handle. Simply returningobj
might lead back to the original error.
Conclusion
The TypeError: Object of type bytes is not JSON serializable
arises because JSON doesn't directly support byte sequences.
- The best practice is usually to decode the
bytes
object to a string using.decode()
before serializing withjson.dumps()
. - For more complex or reusable scenarios, creating a custom
JSONEncoder
or using thedefault
argument provides more structured ways to handlebytes
and potentially other non-standard types during JSON serialization.