Skip to main content

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

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 of bytes.
  • 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 the TypeError for other unsupported types.
  • We pass our custom BytesEncoder class to the cls argument of json.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 is bytes and decodes it.
  • Crucially, if the object isn't bytes, the function should ideally raise a TypeError itself, or return a valid JSON-serializable representation if appropriate for other custom types you might want to handle. Simply returning obj 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 with json.dumps().
  • For more complex or reusable scenarios, creating a custom JSONEncoder or using the default argument provides more structured ways to handle bytes and potentially other non-standard types during JSON serialization.