Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

This lesson is for members only. Join us and get access to thousands of tutorials and a community of expert Pythonistas.

Unlock This Lesson

JSON for Custom Python Objects

In this video you’ll learn how to work with types that are non-serializable.

The json module is not capable of serializing all Python types. Non-serializable types include custom types created from classes, as well as the built-in complex type used to represent imaginary numbers.

Python
json_str = json.dumps(6 + 2j)  # cannot serialize complex object

In order to serialize these types, we must extract the necessary data to recreate the object.

The complex type stores both the real and imaginary parts of the complex number as float. Floats are a type that can be serialized by the dump() and dumps() methods. In the next video, you’ll learn how to encode them into JSON format.

00:00 Welcome back to our series on working with JSON data in Python. In this video, we’re going to learn how to encode custom Python objects or otherwise non-serializable types into JSON format.

00:14 I’m here in Visual Studio Code, and I’ve already typed out a bit of code here to save some time. I’ve got a generic Person class and now I want to serialize a Person object into a string.

00:27 I’ll move down to the bottom here and I’ll type json_str = json.dumps(Person()) and I’ll give him a name of "Will" and an age of 29.

00:41 What I’m trying to do here is create a new Person object and immediately serialize that into a string. Now I’ll simply print the JSON-formatted string to the console.

00:52 So if I right-click here and I choose Run Code, we’ll see that we get a TypeError. Python is telling us that our Person object is not serializable. Let’s take a look at why this is happening.

01:05 Unfortunately for us, the built-in dumps() module only knows how to serialize built-in types. That’s why we can say something like json.dumps() and pass in 3.14 and it will have no problem. But some types are not so easily serializable, like the Python complex type or any other custom type that we create.

01:28 The complex type is used to store complex numbers, which are numbers with an imaginary component. This arises when we try to take the square root of a negative number—but honestly, that just brings back bad memories from high school math class, so let’s not talk too much about it. What’s important here is that you know the complex type is non-serializable, just as our custom Person type is.

01:53 But we still want to store these objects in our JSON files, so what gives? That’s where simplification comes in, and I already like the name. What we need to do is break the object down into simpler parts that can individually be serialized. We should ask ourselves: what is the minimum amount of information necessary to recreate this object?

02:17 Remember, whoever deserializes our JSON on the other end might not know anything about our Person object, so we need to make sure that we serialize everything that’s needed. From here on out, I’m going to use the complex type as an example of how to serialize an otherwise non-serializable type. First, we have to understand how the complex type works. It’s got two parts: a real part and an imaginary part. In the diagram on the right here, 6 + 2j means that 6.0 is our real part, and 2.0 is our imaginary part. Fortunately, each of those numbers can be serialized, and as far as we’re concerned right now, that’s all we need to recreate our complex object after the JSON has been deserialized.

03:07 Remember, the deserialization operation will likely output either a dictionary or a list, so whoever deserializes it is most likely only going to get a list with the numbers 6 and 2 in it, and nothing else.

03:22 Once we have the data from our original object, we can recreate that object by passing the data into the necessary constructor. So in this example here, pretend that we’ve serialized the complex number 3 + 8j. Of course, we can’t actually serialize the complex object in that form, so we just serialized 3 and 8. The person on the other end just deserialized our JSON, and now they’ve got a list of [3, 8] to work with. In order to recreate the original object, all they need to do is pass those numbers into the constructor for the complex class. And as you can see on screen, that gives them a complex object with the same value as our original complex object. There’s one more little hiccup we’ll see later on, but for now, let’s see how we can handle encoding the complex type within our code.

terrymiddleton on May 11, 2019

So…after a little Google searching on serialize and deserialize of json, it has become apparent that the process of serializing and deserializing is simply taking a json object and converting it to a string that can be worked with.

Is this correct.

With an object, it has a certain structure and framework that does not work well/properly with evaluating or working with strings. An output to a file has to be put in a string format so it can be written, while the data may reside in an object.

For example, if I wanted to write out all the books in a certain library and all the books were sitting in an object called library, I would need to “convert” all the books within the object to a string so I could write it to a file or work with it in code.

Am I thinking correctly on this? Terry

Abby Jones on June 28, 2019

I think it is more involved than that, but I am not sure how. I am still learning as well.

Arjun Umathanu on Oct. 7, 2020

import json

class Person:

    def __init__(self, name, age):
        self.name = name
        self.age = age
        self.alive = True

    def serialize(self):
        return {'name': self.name, 'age': self.age, 'alive': self.alive}
>>> json_str = json.dumps(Person('Will', 29).serialize())
>>> print(json_str)
{"name": "Will", "age": 29, "alive": true}  # output :D

Become a Member to join the conversation.