How to Solve "TypeError: Object of type set is not JSON serializable" in Python
The TypeError: Object of type set is not JSON serializable
error occurs when you try to serialize a Python set
object directly using the json.dumps()
method. Sets are not part of the standard JSON data types.
This guide explains why this error occurs and provides the correct solutions, including converting sets to lists, creating custom encoders, and using the simplejson
library as an alternative.
Understanding the Error: JSON and Sets
JSON (JavaScript Object Notation) is a lightweight data-interchange format. It supports basic data types like:
- Objects (similar to Python dictionaries)
- Arrays (similar to Python lists)
- Strings
- Numbers (integers and floating-point)
- Booleans (
true
andfalse
) null
Sets are not directly supported in the JSON standard. Therefore, Python's built-in json
module doesn't know how to serialize a set
by default.
import json
my_set = {'a', 'b', 'c', 'd'}
# ⛔️ TypeError: Object of type set is not JSON serializable
# json_str = json.dumps(my_set)
Solution 1: Convert the Set to a List (Recommended)
The simplest and most common solution is to convert the set
to a list
before serialization:
import json
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(list(my_set)) # Convert to list before serializing
print(json_str) # Output: ["a", "c", "d", "b"] (order may vary)
print(type(json_str)) # Output: <class 'str'>
list(my_set)
: Creates a list containing all the elements of the set. Note: The order of elements in a set is arbitrary, so the order in the list might not match the order you added elements.json.dumps(...)
: Serializes the list to a JSON array string.
This is the best approach in most situations because lists are directly supported by JSON, and it's very concise.
Solution 2: Custom JSON Encoder (for Complex Cases)
If you need more control over how sets (and potentially other custom types) are serialized, you can create a custom JSONEncoder
subclass:
import json
class SetEncoder(json.JSONEncoder):
def default(self, obj):
if isinstance(obj, set):
return list(obj) # Convert set to list
return super().default(obj) # Fallback to default for other types
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, cls=SetEncoder) # Pass the encoder class
print(json_str) # Output: ["a", "b", "d", "c"] (order may vary)
class SetEncoder(json.JSONEncoder):
: We create a subclass ofjson.JSONEncoder
.def default(self, obj):
: This method is called wheneverjson.dumps()
encounters an object it doesn't know how to serialize.if isinstance(obj, set):
: We check if the object is a set.return list(obj)
: If it's a set, we convert it to a list and return it.return super().default(obj)
: If it's not a set, we call thedefault
method of the parent class (JSONEncoder
). This handles the standard JSON types and raises aTypeError
if it encounters an unsupported type. This is important for handling other non-serializable types correctly.
- To use the custom encoder, the
cls
parameter is passed to thejson.dumps
method, setting it to our custom encoder.
Solution 3: Using simplejson
(with iterable_as_array
)
The simplejson
library is a fast, widely-used alternative to the built-in json
module. It offers an option to treat all iterables (including sets) as arrays:
# Install simplejson first: pip install simplejson
import simplejson as json # Use 'as json' for convenience
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, iterable_as_array=True) # Serialize set as array
print(json_str) # Output: ["a", "b", "c", "d"] (order may vary)
iterable_as_array=True
: This tellssimplejson
to treat any iterable object (including sets) as if it were a list/array during serialization.
While this works, it's generally better to be explicit and convert your sets to lists using list(my_set)
before using the standard json
module. This improves code clarity and avoids relying on a specific feature of simplejson
.
Using the default
Argument (Less Flexible)
You can pass the list
constructor to the default
argument of the json.dumps()
method:
import json
my_set = {'a', 'b', 'c', 'd'}
json_str = json.dumps(my_set, default=list)
print(json_str)
- The
default
argument is a function that returns a serializable object. - This is less flexible than using a custom
JSONEncoder
because it requires you to create a new function every time you want to handle different classes.
Conclusion
The TypeError: Object of type set is not JSON serializable
error occurs because JSON doesn't have a native set data type.
- The best solution is to convert the set to a list before serializing it with
json.dumps()
. - For more complex scenarios where you need to serialize other custom types along with sets, a custom
JSONEncoder
subclass gives you fine-grained control.simplejson
withiterable_as_array=True
provides an alternative, but explicitly converting to a list is generally preferred for clarity and compatibility. - Avoid using the
default
argument to thejson.dumps
function for general use cases.