- Python JSON – Custom Class Serialization
- 1.1. Add default Serializer Method
- 1.2. Use ‘default’ attribute on json.dumps()
- 1.2. Use ‘cls’ attribute on json.dumps()
- Make a Python Class JSON Serializable
- Write custom JSONEncoder to make class JSON serializable
- Use toJSON() Method to make class JSON serializable
- Use the jsonpickle module to make class JSON serializable
- Inheriting from dict to make class JSON serializable
- Next Steps
- About Vishal
- Related Tutorial Topics:
- Python Exercises and Quizzes
Python JSON – Custom Class Serialization
Learn to serialize a complex python class (e.g. User ) and write serialized JSON data in file by extending JSONEncoder and custom serialization method.
In Python serialize complex object to JSON example, we have following User class. Here, birthdate of type datetime.
class User: def __init__(self, id, name, birthdate): self.id = id self.name = name self.birthdate = birthdate
If we don’t use the custom serialization, we will get the error : TypeError: Object of type User is not JSON serializable.
1. Python Custom Serialization using Serializer Method
1.1. Add default Serializer Method
Add a default serializer method to User class itself. This will be invoked by Python while dumping the JSON.
We can write the complete logic to convert the User object to python dictionary object here.
class User: def __init__(self, id, name, birthdate): self.id = id self.name = name self.birthdate = birthdate def to_dict(u): if isinstance(u, User): dict = < "id": u.id, "name": u.name, "birthdate": u.birthdate.strftime("%d %b %y") >return dict else: type_name = u.__class__.__name__ raise TypeError("Unexpected type ".format(type_name))
1.2. Use ‘default’ attribute on json.dumps()
Next, to use this serializer method, use the default attribute in json.dump() method. It will be automatically called by python while converting the complex object to JSON.
import json from user import User import datetime from UserEncoder import UserEncoder u = User(1, 'TestUser', datetime.datetime(1991, 1, 6)) # Convert User object to JSON print(json.dumps(u, default=User.to_dict))
2. Python Custom Serialization using JSONEncoder
Another way to add the similar complex object to JSON converter logic – is to extend the JSONEncoder class.
The following UserEncoder class overrides the default method of UserEncoder class and provides the logic to convert the complex class to JSON.
import json import datetime from user import User class UserEncoder(json.JSONEncoder): def default(self, u): if isinstance(u, User): dict = < "id": u.id, "name": u.name, "birthdate": u.birthdate.strftime("%d %b %y") >return dict else: type_name = u.__class__.__name__ raise TypeError("Unexpected type ".format(type_name))
1.2. Use ‘cls’ attribute on json.dumps()
To use custom JSONEncoder , use the cls attribute in json.dump() method. It will be automatically called by python while converting the complex object to JSON.
import json from user import User import datetime from UserEncoder import UserEncoder u = User(1, 'TestUser', datetime.datetime(1991, 1, 6)) # Convert User object to JSON print(json.dumps(u, cls=UserEncoder))
Make a Python Class JSON Serializable
You are here because when you try to encode a custom Python object into a JSON format, you received a TypeError: Object of type SampleClass is not JSON serializable . In this article, I will show you how to serialize arbitrary Python objects to JSON so that you can convert any custom Python objects into JSON formatted data.
The built-in json module of Python can only handle Python primitives types that have a direct JSON equivalent. i.e., The fundamental problem is that the JSON encoder json.dump() and json.dumps() only knows how to serialize the basic set of object types by default (e.g., dictionary, lists, strings, numbers, None, etc.). To solve this, we need to build a custom encoder to make our Class JSON serializable.
There are multiple ways to Make a Python Class JSON Serializable. You can pick the one which best suited to your problem complexity. Let’ understand each one-by-one.
Further Reading:
Goals of this lesson:
- Write your own custom JSON Encoder to make class JSON serializable
- Create custom toJSON() Method to make Python class JSON serializable
- Use jsonpickle module to make class JSON serializable
- How to Inherit class from dict to make class JSON serializable
Write custom JSONEncoder to make class JSON serializable
Python json module has a JSONEncoder class. You can extend it If you want more customized output. i.e., you will have to subclass JSONEncoder so you can implement your custom JSON serialization.
The json.dump() and json.dumps() method of the JSON module has a cls kwarg. Using this argument, you can pass a custom JSON Encoder, which tells json.dump() or json.dumps() method how to encode your object into JSON formatted data. The default JSONEncoder class has a default() method that will be used when we execute JSONEncoder.encode(object) . This method converts only basic types into JSON.
Your custom JSONEncoder subclass will override the default() method to serialize additional types. Specify it with the cls kwarg in json.dumps() method; otherwise, default JSONEncoder is used. Example: json.dumps(cls=CustomEncoder) . Let’s see the example now.
import json from json import JSONEncoder class Employee: def __init__(self, name, salary, address): self.name = name self.salary = salary self.address = address class Address: def __init__(self, city, street, pin): self.city = city self.street = street self.pin = pin # subclass JSONEncoder class EmployeeEncoder(JSONEncoder): def default(self, o): return o.__dict__ address = Address("Alpharetta", "7258 Spring Street", "30004") employee = Employee("John", 9000, address) print("Printing to check how it will look like") print(EmployeeEncoder().encode(employee)) print("Encode Employee Object into JSON formatted Data using custom JSONEncoder") employeeJSONData = json.dumps(employee, indent=4, cls=EmployeeEncoder) print(employeeJSONData) # Let's load it using the load method to check if we can decode it or not. print("Decode JSON formatted Data") employeeJSON = json.loads(employeeJSONData) print(employeeJSON)
Printing to check how it will look like > Encode Object into JSON formatted Data using custom JSONEncoder < "name": "John", "salary": 9000, "address": < "city": "Alpharetta", "street": "7258 Spring Street", "pin": "30004" >> Decode JSON formatted Data >
- The EmployeeEncoder class overrides the default() method of a JSONEncoder class, so we able to convert custom Python object into JSON.
- In EmployeeEncoder class we converted our Object into a Python dictionary format.
Note: Refer to decode JSON into the Custom Python Object instead of a dictionary if you also want to decode JSON back to the Custom Python Object.
Use toJSON() Method to make class JSON serializable
A simple and straightforward solution. Instead of making class JSON serializable, we can implement a serializer method in the class.
So we don’t need to write custom JSONEncoder.
This new toJSON() serializer method will return the JSON representation of the Object. i.e., It will convert custom Python Object to JSON string. Let’ see the example.
import json class Employee: def __init__(self, name, salary, address): self.name = name self.salary = salary self.address = address def toJson(self): return json.dumps(self, default=lambda o: o.__dict__) class Address: def __init__(self, city, street, pin): self.city = city self.street = street self.pin = pin address = Address("Alpharetta", "7258 Spring Street", "30004") employee = Employee("John", 9000, address) print("Encode into JSON formatted Data") employeeJSONData = json.dumps(employee.toJson(), indent=4) print(employeeJSONData) # Let's load it using the load method to check if we can decode it or not. print("Decode JSON formatted Data") employeeJSON = json.loads(employeeJSONData) print(employeeJSON)
Encode into JSON formatted Data ">" Decode JSON formatted Data >
- As you can see we are able to encode and decode Employee object into JSON formatted stream.
- We used the use default argument of json.dumps() method to serialize additional types to dict and converted newly created dict to JSON string.
Note: Refer to decode JSON into the Custom Python Object instead of a dictionary if you also want to decode JSON back to the Custom Python Object.
Use the jsonpickle module to make class JSON serializable
jsonpickle is a Python library designed to work with complex Python Objects. You can use jsonpickle for serialization complex Python objects into JSON. Also, and deserialization from JSON to complex Python objects.
As you know The built-in json module of Python can only handle Python primitives types that have a direct JSON equivalent (e.g., dictionary, lists, strings, Numbers, None, etc.).
jsonpickle builds on top of these libraries and allows more complex data structures to be serialized to JSON. jsonpickle is highly configurable and extendable–allowing the user to choose the JSON backend and add additional backends.
- Install jsonpickle using pip install jsonpickle
- Execute jsonpickle.encode(object) to serialize custom Python Object.
You can refer to Jsonpickle Documentation for more detail. Let’s see the jsonpickle example to make a Python class JSON serializable.
import json import jsonpickle from json import JSONEncoder class Employee(object): def __init__(self, name, salary, address): self.name = name self.salary = salary self.address = address class Address(object): def __init__(self, city, street, pin): self.city = city self.street = street self.pin = pin address = Address("Alpharetta", "7258 Spring Street", "30004") employee = Employee("John", 9000, address) print("Encode Object into JSON formatted Data using jsonpickle") empJSON = jsonpickle.encode(employee, unpicklable=False) print("Writing JSON Encode data into Python String") employeeJSONData = json.dumps(empJSON, indent=4) print(employeeJSONData) print("Decode JSON formatted Data using jsonpickle") EmployeeJSON = jsonpickle.decode(employeeJSONData) print(EmployeeJSON) # Let's load it using the load method to check if we can decode it or not. print("Load JSON using loads() method") employeeJSON = json.loads(EmployeeJSON) print(employeeJSON)
Encode Object into JSON formatted Data using jsonpickle Writing JSON Encode data into Python String ", \"name\": \"John\", \"salary\": 9000>" Decode JSON formatted Data using jsonpickle , "name": "John", "salary": 9000> Load JSON using loads() method , 'name': 'John', 'salary': 9000>
I used unpicklable=False because I don’t want to decode this data back to Object. If you wish to decode JSON back to Employee Object use unpicklable=True . or please refer to load JSON data directly into Object. There I mentioned how to use jsonpickle to load JSON data directly into Object.
Also, you can try the jsons module to make class JSON serializable.
Inheriting from dict to make class JSON serializable
If you don’t want to write a custom encoder, also, if you are not willing to use jsonpickle, you can use this solution. Check if this solution works for you. This solution works if your Class is not complicated. For trickier things, you will have to set keys explicitly.
This method is useful for those who cannot modify their json.dumps(obj) call to include custom encoder. i.e. If you want to call json.dumps(obj) as-is, then a simple solution is inheriting from dict.
So, in this case, you don’t need to change the call to json.dumps() . I mean, what if you are passing an object and JSON dumping is happening inside different application components or framework where you don’t have control to modify json.dumps() call.
import json class Employee(dict): def __init__(self, name, age, salary, address): dict.__init__(self, name=name, age=age, salary=salary, address=address) class Address(dict): def __init__(self, city, street, pin): dict.__init__(self, city=city, street=street, pin=pin) address = Address("Alpharetta", "7258 Spring Street", "30004") employee = Employee("John", 36, 9000, address) print("Encode into JSON formatted Data") employeeJSON = json.dumps(employee) print(employeeJSON) # Let's load it using the load method to check if we can decode it or not. print("Decode JSON formatted Data") employeeJSONData = json.loads(employeeJSON) print(employeeJSONData)
Encode into JSON formatted Data > Decode JSON formatted Data >
Next Steps
I want to hear from you. What do you think of this article? Or maybe I missed one of the ways to make Python Class JSON serializable. Either way, let me know by leaving a comment below.
Also, try to solve the Python JSON Exercise to have a better understanding of Working with JSON Data in Python.
Did you find this page helpful? Let others know about it. Sharing helps me continue to create free Python resources.
About Vishal
I’m Vishal Hule, Founder of PYnative.com. I am a Python developer, and I love to write articles to help students, developers, and learners. Follow me on Twitter
Related Tutorial Topics:
Python Exercises and Quizzes
Free coding exercises and quizzes cover Python basics, data structure, data analytics, and more.
- 15+ Topic-specific Exercises and Quizzes
- Each Exercise contains 10 questions
- Each Quiz contains 12-15 MCQ