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

by | Programming, Python, Tips

This error occurs when you pass a file to the json.dumps() method. You can solve this error by calling read() or readlines() to return a string or a list, respectively. For example,

import json

with open('file_name', 'r') as f:
    json_str = json.dumps(f.readlines())

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


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

Example

Let’s look at an example of a text file called leptons.txt that contains the names of three particles.

muon
electron
tau

Next, we will load the data into a program and attempt to serialize the data into a JSON string by passing the file object to the json.dumps() method.

 with open('leptons.txt', 'r') as f:

     json_str = json.dumps(f)

Let’s run the code to get the result:

TypeError: Object of type TextIOWrapper is not JSON serializable

The error occurs because f is a file object, which is not a JSON serializable type.

Solution #1 Call readlines()

We can solve the error by calling the readlines() method on the file object, which returns a list containing the lines in the file. List is a JSON serializable type. Let’s look at the updated code:

with open('leptons.txt', 'r') as f:

    lst = f.readlines()

    lst = [string.strip() for string in lst]

    json_str = json.dumps(lst)

    print(json_str)

    print(type(json_str))

In the above code, we use list comprehension to call the strip method on the strings in the list to remove the new line character '\n'. Let’s run the code to see the result:

["muon", "electron", "tau"]
<class 'str'>

We successfully serialized the data in the file to a JSON string.

Solution #2: Define a custom function for default kwarg

We can also solve this error by defining a custom function that calls the readlines() method on the file object 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 format.

import json

def serialize_file(obj):

    if isinstance(obj, TextIOWrapper):

        lst = obj.readlines()

        lst = [string.strip() for string in lst]

        return lst

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

The custom function checks if the object is type TextIOWrapper and then calls the readlines() method to return a list containing each line in the file as a list item.

Otherwise, the custom function raises a TypeError.

Let’s set the default keyword to our custom function and run the code:

with open('leptons.txt', 'r') as f:
   
    json_str = json.dumps(lst, default=serialize_file)
   
    print(json_str)
   
    print(type(json_str))
["muon", "electron", "tau"]
<class 'str'>

We successfully serialized the data in the file to a JSON string.

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 of type TextIOWrapper, calls the readlines() method to get a list containing lines in the file and returns the list.

import json

class FileEncoder(json.JSONEncoder):

    def default(self, obj):

        if isinstance(obj, TextIOWrapper):

            lst = obj.readlines()

            lst = [string.strip() for string in lst]

            return lst

        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:

with open('leptons.txt', 'r') as f:

    json_str = json.dumps(lst,cls=FileEncoder)

    print(json_str)

    print(type(json_str))
["muon", "electron", "tau"]
<class 'str'>

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!

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!

Follow the Research Scientist Pod on Social media!