Python json.decoder.JSONDecoder.object_hook Attribute
The Python json.decoder.JSONDecoder.object_hook attribute is used to specify a custom function for decoding JSON objects into custom Python objects.
It is useful when you want to deserialize JSON dictionaries into instances of a specific class rather than just Python dictionaries.
Syntax
Following is the syntax of using the object_hook attribute −
json.decoder.JSONDecoder(object_hook=function)
Parameter
It is a user-defined function that transforms parsed JSON objects (dictionaries) into custom Python objects.
Return Value
The object_hook attribute modifies the default dictionary decoding behavior and returns an instance of the specified custom class.
Example: Basic Usage of object_hook
In this example, we use the object_hook attribute to convert a JSON object into a Python class instance −
import json
# Define a custom class
class Person:
def __init__(self, name, age, city):
self.name = name
self.age = age
self.city = city
def __repr__(self):
return f"Person(name={self.name}, age={self.age}, city={self.city})"
# Define a function to convert JSON object to Person instance
def person_decoder(obj):
return Person(obj['name'], obj['age'], obj['city'])
# JSON string
json_string = '{"name": "Alice", "age": 30, "city": "New York"}'
# Create JSONDecoder instance with object_hook
decoder = json.decoder.JSONDecoder(object_hook=person_decoder)
# Decode JSON into a custom object
parsed_data = decoder.decode(json_string)
print("Decoded Custom Object:", parsed_data)
Following is the output obtained −
Decoded Custom Object: Person(name=Alice, age=30, city=New York)
Example: Handling Nested JSON Structures
The object_hook attribute can be extended to handle nested JSON structures −
import json
# Define a custom class
class Employee:
def __init__(self, name, department):
self.name = name
self.department = department
def __repr__(self):
return f"Employee(name={self.name}, department={self.department})"
# Custom decoder function
def employee_decoder(obj):
if "name" in obj and "department" in obj:
return Employee(obj['name'], obj['department'])
return obj # Return unchanged for other objects
# JSON string containing nested data
json_string = '{"company": "TechCorp", "employee": {"name": "John", "department": "IT"}}'
# Create JSONDecoder instance with object_hook
decoder = json.decoder.JSONDecoder(object_hook=employee_decoder)
# Decode JSON into a custom object
parsed_data = decoder.decode(json_string)
print("Decoded Nested Object:", parsed_data)
Following is the output of the above code −
Decoded Nested Object: {'company': 'TechCorp', 'employee': Employee(name=John, department=IT)}
Example: Ignoring Certain Keys in JSON
The object_hook attribute can be used to filter out unnecessary keys from JSON −
import json
# Custom decoder function to remove unwanted keys
def filter_keys(obj):
obj.pop("ignore_this", None) # Remove the key if it exists
return obj
# JSON string with unnecessary data
json_string = '{"name": "Alice", "age": 28, "ignore_this": "remove me"}'
# Create JSONDecoder instance with object_hook
decoder = json.decoder.JSONDecoder(object_hook=filter_keys)
# Decode JSON
parsed_data = decoder.decode(json_string)
print("Filtered JSON:", parsed_data)
We get the output as shown below −
Filtered JSON: {'name': 'Alice', 'age': 28}
Example: Changing Key Names while Decoding
The object_hook attribute can be used to rename keys dynamically −
import json
# Custom function to rename JSON keys
def rename_keys(obj):
new_obj = {}
for key, value in obj.items():
new_obj[f"custom_{key}"] = value # Prefix key names with 'custom_'
return new_obj
# JSON string
json_string = '{"name": "Charlie", "age": 35, "city": "Boston"}'
# Create JSONDecoder instance with object_hook
decoder = json.decoder.JSONDecoder(object_hook=rename_keys)
# Decode JSON
parsed_data = decoder.decode(json_string)
print("Renamed Keys JSON:", parsed_data)
The result produced is as follows −
Renamed Keys JSON: {'custom_name': 'Charlie', 'custom_age': 35, 'custom_city': 'Boston'}