How to Solve Python TypeError: Object of type dict_items is not JSON serializable

by | Programming, Python, Tips

This error occurs when we try to serialize a dict_items object to a JSON string using the json.dumps() method. You can solve this error by converting the dict_items object to a list using the built-in list() method. For example,

import json 

my_dict = {'particle':'electron', 'mass':0.511, 'charge': -1}

items = list(my_dict.items())

json_str = json.dumps(items)

This tutorial will go through the error in detail and how to solve it with code examples.


TypeError: Object of type dict_items 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_items” tells us the error is due to an illegal operation with an object of the dict_items class. dict_items is a view object that displays all of the key-value tuple pairs 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_items type.

Example

Let’s look at an example of serializing a dict_items 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 items method on the dictionary object to get the dict_items view object.

items = my_dict.items()

Next, we will attempt to serialize the dict_items object to a JSON string by passing it to the json.dumps() method.

json_str = json.dumps(items)

print(json_str)

Let’s run the code to see what happens:

TypeError: Object of type dict_items is not JSON serializable

The error occurs because items is a dict_itemss 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(items))
<class 'dict_items'>

Solution #1: Convert dict_items to list

The simplest way to solve this error is to convert the dict_items 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}

items = list(my_dict.items())

json_str = json.dumps(items)

print(json_str)

Let’s run the code to get the JSON string containing the list of key-value tuple pairs:

[["pizza", "tartufo"], ["is_vegetarian", false], ["price", 13.99]]

Solution #2: Define a custom function for the default keyword argument

We can also solve this error by defining a custom function that converts a dict_items 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_items(obj):

    if isinstance(obj, abc.ItemsView):

        return list(obj)

    raise TypeError ("Type %s is not serializable" % type(obj))

To check if an object is an instance of dict_items 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 items 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:

import json 

my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99}

items = my_dict.items()

json_str = json.dumps(items, default=serialize_dict_items)

print(json_str)

Let’s run the code to see the JSON string:

[["pizza", "tartufo"], ["is_vegetarian", false], ["price", 13.99]]

We can also set default to list. Let’s look at the revised code:

import json 

my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99}

items = my_dict.items()

json_str = json.dumps(items, default=list)

print(json_str)

Let’s run the code to see the JSON string:

[["pizza", "tartufo"], ["is_vegetarian", false], ["price", 13.99]]

Solution #3: Define a JSONEncoder subclass for the cls keyword argument

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_items_encoder(json.JSONEncoder):

    def default(self, obj):

        if isinstance(obj, abc.ItemsView):

            return list(obj)

        return json.JSONEncoder.default(self, obj)

Similar to the custom function, the default method of the dict_items_encoder class checks if the object is an instance of dict_items using the ItemsView 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:

import json 

my_dict = {'pizza':'tartufo', 'is_vegetarian':False, 'price': 13.99}

items = my_dict.items()

json_str = json.dumps(items, cls=dict_items_encoder)

print(json_str)

Let’s run the code to see the result:

[["pizza", "tartufo"], ["is_vegetarian", false], ["price", 13.99]]

Below is the collection of objects that the JSONEncoder class supports by default, and their JSON equivalent.

PythonJSON
dictobject
list, tuplearray
strstring
int, float, int- & float- derived Enumsnumber
Truetrue
Falsefalse
Nonenull
JSONEncoder Supported objects and types by default

Summary

Congratulations on reading to the end of this tutorial!

For further reading on “not JSON serializable” TypeErrors, go to the articles:

Go to the online courses page on Python to learn more about Python for data science and machine learning.

Have fun and happy researching!

Research Scientist at Moogsoft | + posts

Suf is a research scientist at Moogsoft, specializing in Natural Language Processing and Complex Networks. Previously he was a Postdoctoral Research Fellow in Data Science working on adaptations of cutting-edge physics analysis techniques to data-intensive problems in industry. In another life, he was an experimental particle physicist working on the ATLAS Experiment of the Large Hadron Collider. His passion is to share his experience as an academic moving into industry while continuing to pursue research. Find out more about the creator of the Research Scientist Pod here and sign up to the mailing list here!