This error occurs when we try to serialize a dict_keys
object to a JSON string using the json.dumps()
method. You can solve this error by converting the dict_keys
object to a list using the built-in list()
method. For example,
import json my_dict = {'particle':'electron', 'mass':0.511, 'charge': -1} keys = list(my_dict.keys()) json_str = json.dumps(keys)
This tutorial will go through the error in detail and how to solve it with code examples.
Table of contents
TypeError: Object of type dict_keys is not JSON Serializable
Let’s break up the error message to understand what the error means. TypeError occurs whenever you attempt to use an illegal operation for a specific data type. The part “Object of type dict_values” tells us the error is due to an illegal operation with an object of the dict_keys
class. dict_keys
is a view object that displays all of the keys in the given dictionary. The view object changes as the dictionary changes.
Serialization in Python refers to converting a Python object into a transmittable format that we can recreate when needed using deserialization. JSON serialization returns a human-readable string form called a JSON string. The JSON encoder json.dump() and json.dumps() can only serialize certain object types like dictionaries, lists, or strings.
“is not JSON serializable” informs us that the JSON serialization is an illegal operation for the dict_keys
type.
Example
Let’s look at an example of serializing a dict_keys
view object. First, we will import the json
module and then define a dictionary.
import json my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99}
The above dictionary contains information about a pizza
. Next, we will call the keys
method on the dictionary object to get the dict_keys
view object.
keys = my_dict.keys()
Next, we will attempt to serialize the dict_keys
object to a JSON string by passing it to the json.dumps()
method.
json_str = json.dumps(keys) print(json_str)
Let’s run the code to see what happens:
TypeError: Object of type dict_keys is not JSON serializable
The error occurs because keys
is a dict_keys
object, which is not JSON serializable. We can check the type of an object by using the built-in type()
method as follows:
print(type(keys))
<class 'dict_keys'>
Solution #1: Convert dict_keys to list
The simplest way to solve this error is to convert the dict_keys
object to a list using the built-in list()
method. The list
data type is JSON serializable.
Let’s look at the revised code:
import json my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99} keys = list(my_dict.keys()) json_str = json.dumps(keys) print(json_str)
Let’s run the code to get the JSON string containing the list of dictionary keys:
["pizza", "is_vegetarian", "price"]
Solution #2: Define a custom function for the default kwarg
We can also solve this error by defining a custom function that converts a dict_keys
object to a list
. We can then pass the function as the default argument for the json.dumps()
method. The function we set as the default
keyword argument gets called for objects that are not JSON serializable. Let’s look at the custom function:
import json from collections import abc def serialize_dict_keys(obj): if isinstance(obj, abc.KeysView): return list(obj) raise TypeError ("Type %s is not serializable" % type(obj))
To check if an object is an instance of dict_keys
we can use the collections.abc module, which provides abstract base classes to test whether a class provides a particular interface.
In this case, the Abstract Base Class (ABC) we need is dictionary keys views.
Note that if the object obj
is not an instance of KeysView
the function will raise a TypeError. Let’s set the default
keyword argument to our custom function and run the code:
my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99} keys = my_dict.keys() json_str = json.dumps(keys, default=serialize_dict_keys) print(json_str)
Let’s run the code to see the JSON string:
["pizza", "is_vegetarian", "price"]
We can also set default
to list
. Let’s look at the revised code:
my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99} keys = my_dict.keys() json_str = json.dumps(keys, default=list) print(json_str)
Let’s run the code to see the JSON string:
["pizza", "is_vegetarian", "price"]
Solution #3: Define a JSONEncoder subclass for the cls kwarg
We can also solve this error by building a custom JSONEncoder
subclass. This subclass will override the default method to serialize additional types.
import json from collections import abc class dict_keys_encoder(json.JSONEncoder): def default(self, obj): if isinstance(obj, abc.KeysView): return list(obj) return json.JSONEncoder.default(self, obj)
Similar to the custom function, the default
method of the dict_keys_encoder
class checks if the object is an instance of dict_keys
using the KeysView
ABC and converts it to a list and returns it.
We have to specify the custom JSONEncoder
subclass with the cls
keyword argument. Otherwise, JSONEncoder
is used. Let’s look at the updated code:
my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99} keys = my_dict.keys() json_str = json.dumps(keys, cls=dict_keys_encoder) print(json_str)
Let’s run the code to see the result:
["pizza", "is_vegetarian", "price"]
Below is the collection of objects that the JSONEncoder
class supports by default, and their JSON
equivalent.
Python | JSON |
---|---|
dict | object |
list, tuple | array |
str | string |
int, float, int- & float- derived Enums | number |
True | true |
False | false |
None | null |
Summary
Congratulations on reading to the end of this tutorial!
For further reading on “not JSON serializable” TypeErrors, go to the articles:
- How to Solve Python TypeError: Object of type dict_values is not JSON Serializable
- How to Solve Python TypeError: Object of type dict_items is not JSON serializable
- How to Solve Python TypeError: Object of type bool_ is not JSON serializable
Go to the online courses page on Python to learn more about Python for data science and machine learning.
Have fun and happy researching!
Suf is a senior advisor in data science with deep expertise in Natural Language Processing, Complex Networks, and Anomaly Detection. Formerly a postdoctoral research fellow, he applied advanced physics techniques to tackle real-world, data-heavy industry challenges. Before that, he was a particle physicist at the ATLAS Experiment of the Large Hadron Collider. Now, he’s focused on bringing more fun and curiosity to the world of science and research online.