Python Custom JSON Encoder and Decoder

Write a Python program to create a custom JSON encoder and decoder for complex Python objects.

The problem involves creating custom "JSON" encoder and decoder classes for serializing and deserializing complex Python objects that are not natively supported by the "json" module. Specifically, this involves handling instances of user-defined classes, such as "Address" and "Person", by converting them to JSON-compatible dictionaries and back into Python objects. The solution requires subclassing "json.JSONEncoder" for custom encoding and defining a function to handle custom decoding.

Sample Solution:

Python Code :

import json

# Define the Address and Person classes
class Address:
    def __init__(self, street, city, state, zip_code):
        self.street = street
        self.city = city
        self.state = state
        self.zip_code = zip_code

class Person:
    def __init__(self, name, age, address):
        self.name = name
        self.age = age
        self.address = address

# Custom JSON Encoder
class ComplexEncoder(json.JSONEncoder):
    def default(self, obj):
        if isinstance(obj, Address):
            return {
                '__type__': 'Address',
                'street': obj.street,
                'city': obj.city,
                'state': obj.state,
                'zip_code': obj.zip_code
        elif isinstance(obj, Person):
            return {
                '__type__': 'Person',
                'name': obj.name,
                'age': obj.age,
                'address': obj.address
        return json.JSONEncoder.default(self, obj)

# Custom JSON Decoder
def complex_decoder(dct):
    if '__type__' in dct:
        if dct['__type__'] == 'Address':
            return Address(dct['street'], dct['city'], dct['state'], dct['zip_code'])
        elif dct['__type__'] == 'Person':
            address = dct['address']
            if isinstance(address, dict):
                address = complex_decoder(address)
            return Person(dct['name'], dct['age'], address)
    return dct

# Example usage
address = Address("123 ABCD St.", "Paris", "CA", "12345")
person = Person("Roslindis Bronwen", 30, address)

# Serialize to JSON
person_json = json.dumps(person, cls=ComplexEncoder)
print("Serialized JSON:", person_json)

# Deserialize from JSON
decoded_person = json.loads(person_json, object_hook=complex_decoder)
print("\nDecoded Object:", decoded_person.name, decoded_person.age, decoded_person.address.street)


Serialized JSON: {"__type__": "Person", "name": "Roslindis Bronwen", "age": 30, "address": {"__type__": "Address", "street": "123 ABCD St.", "city": "Paris", "state": "CA", "zip_code": "12345"}}

Decoded Object: Roslindis Bronwen 30 123 ABCD St.


  • Importing Libraries: The code starts by importing the "json" library, which provides functions for encoding Python objects as JSON strings and decoding JSON strings back into Python objects.
  • Defining Classes: Two classes are defined:
  • Address: Represents a physical address with attributes for street, city, state, and zip code.
  • Person: Represents a person with attributes for name, age, and address (an instance of the "Address" class).
  • Custom JSON Encoder: A custom JSON encoder class named "ComplexEncoder" is defined by subclassing "json.JSONEncoder". This encoder is responsible for converting instances of the "Address" and "Person" classes into JSON-compatible dictionaries during serialization.
  • Custom JSON Decoder: A custom JSON decoder function named "complex_decoder()" is defined. This function is used as the 'object_hook' parameter when deserializing JSON strings. It converts JSON dictionaries back into instances of the "Address" and "Person" classes.
  • Example:
    An instance of "Address" and an instance of "Person" are created.
  • The "Person" object is serialized to JSON using "json.dumps()" with the custom encoder "ComplexEncoder".
  • The serialized JSON string is printed.
  • The JSON string is deserialized back into a Python object using "json.loads()" with the custom decoder "complex_decoder".
  • The decoded 'Person' object's attributes are printed.

Python Code Editor :

Have another way to solve this solution? Contribute your code (and comments) through Disqus.

Previous: Python A* Search Algorithm for Pathfinding.
Next: Python Bloom Filter implementation.

What is the difficulty level of this exercise?

Test your Programming skills with w3resource's quiz.

Follow us on Facebook and Twitter for latest update.