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 theTypeErrorfor other unsupported types. - We pass our custom
BytesEncoderclass to theclsargument 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_serializerfunction checks if the object isbytesand decodes it. - Crucially, if the object isn't
bytes, the function should ideally raise aTypeErroritself, or return a valid JSON-serializable representation if appropriate for other custom types you might want to handle. Simply returningobjmight 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
bytesobject to a string using.decode()before serializing withjson.dumps(). - For more complex or reusable scenarios, creating a custom
JSONEncoderor using thedefaultargument provides more structured ways to handlebytesand potentially other non-standard types during JSON serialization.