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

by | Programming, Python, Tips

This error occurs when you try to serialize a numpy.ndarray object to a JSON string using the json.dumps() method. Yous can solve this by calling the tolist() method on the ndarray to convert it to a Python list and then pass the list to the json.dumps() method call. For example,

json_str = json.dumps(arr.tolist())

This tutorial will go through how to solve the error with code examples.


TypeError: Object of type ndarray 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 ndarray” tells us the error is due to an illegal operation with an ndarray object.

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 ndarray type.

Example

Let’s look at an example of serializing a ndarray.

import json
import numpy as np

arr = np.array([10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22])

my_dict = {}

my_dict['numbers'] = arr

json_str = json.dumps(my_dict)

print(json_str)

In the above code we define a ndarray containing twenty integers. Next, we define a dictionary with a single item consisting of the key ‘numbers‘ and the ndarray arr as the value. We then pass the dictionary to the json.dumps() method to serialize it. Let’s run the code to see what happens:

TypeError: Object of type ndarray is not JSON serializable

The error occurs because the dictionary my_dict contains an ndarray and ndarray is not a suitable type for JSON serialization.

Solution #1: Convert ndarray to list using tolist()

The simplest way to solve this error is to call the tolist() method on the ndarray to get a list. List objects are JSON serializable. We can then store the list in the dictionary and pass the dictionary to the json.dumps() method to serialize it. Let’s look at the updated code:

import json

import numpy as np
arr = np.array([10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22])
my_dict = {}
my_dict['numbers'] = arr.tolist()
json_str = json.dumps(my_dict)
print(json_str)

Let’s run the code to print the JSON string to the console:

{"numbers": [10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22]}

Solution #2: Define a custom function for default kwarg

We can also solve this error by defining a custom function that converts the ndarray to a list and passing this function to json.dumps() as the default keyword argument. The default value for the keyword argument default is None. We can set default to a function for objects that are not serializable to convert them to a serializable type.

import json
import numpy as np

def serialize_ndarray(obj):

    if isinstance(obj, np.ndarray):

        return obj.tolist()

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

The custom function checks if the object is type np.ndarray (where np is an alias for numpy) and then converts it to a list using tolist(). Otherwise, it raises a TypeError. Let’s set the default keyword to our custom function and run the code:

arr = np.array([10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22])
my_dict = {}
my_dict['numbers'] = arr
json_str = json.dumps(my_dict, default=serialize_ndarray)
print(json_str)
{"numbers": [10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22]}

Solution #3: Define a JSONEncoder subclass for the cls kwarg

The third way we can solve this error is by building a custom JSONEncoder subclass. This subclass will override the default method to serialize additional types. Similar to the custom function, the default method checks if the object is type ndarray, converts it to a list and returns it.

import json
import numpy as np

class NDArrayEncoder(json.JSONEncoder):

    def default(self, obj):

        if isinstance(obj, np.ndarray):

            return obj.tolist()

        return json.JSONEncoder.default(self, obj)

We have to specify the custom JSONEncoder subclass with the cls keyword argument. Otherwise, JSONEncoder is used. Let’s look at the updated code:

arr = np.array([10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22])
my_dict = {}
my_dict['numbers'] = arr
json_str = json.dumps(my_dict, cls=NDArrayEncoder)
print(json_str)

Let’s run the code to print the JSON string to the console.

{"numbers": [10, 47, 33, 95, 11, 82, 61, 1, 82, 4, 3, 31, 65, 54, 42, 61, 53, 9, 36, 22]}

Below is the collection of objects that the JSONEncoder class supports 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 errors involving JSON serialization, 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!

Profile Picture
Senior Advisor, Data Science | [email protected] | + posts

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.

Buy Me a Coffee ✨