Reading JSON File Using Object-Oriented Approach
Last Updated: August 2, 2026
In this article, we will learn how to read a json file using object oriented approach.
Let’s consider the below JSON file,
employees.json
[
{
"id": "1",
"first_name": "David",
"last_name": "Brown",
"gender": "Male",
"date_of_birth": "1983-08-26",
"nationality": "United States"
},
{
"id": "2",
"first_name": "Laura",
"last_name": "White",
"gender": "Female",
"date_of_birth": "1993-05-17",
"nationality": "United States"
}
]
For demonstration purpose, the above json file has a list of only two employee records.
Each employee has fields, id, first_name, last_name, gender, date_of_birth and nationality.
Let’s design an object-oriented solution for reading and accessing data from the above JSON file.
employee.py
from json import load
from pathlib import Path
class Employee:
def __init__(self, emp_id: str):
self.emp_id = str(emp_id)
self._path = self._json_file_path
self._data = self._load_json_data
self._info = None
@property
def _json_file_path(self):
"""Returns a JSON file path object"""
path = Path("employees.json")
if not path.exists():
raise FileNotFoundError(f"{path} does not exist")
return path
@property
def _load_json_data(self):
"""
Loads the JSON file and returns the employee data for the employee corresponding
to the employee ID supplied during object instantiation.
Returns an empty dictionary if the employee id does not exist in the JSON file
"""
with open(self._path, "r") as json_file:
json_object = load(json_file)
for item in json_object:
if item["id"] == self.emp_id:
return item
return {}
@property
def info(self):
if not self._info:
self._info = EmployeeInfo(self._data)
return self._info
class EmployeeInfo:
def __init__(self, data):
self._data = data
@property
def first_name(self):
return self._data.get("first_name", "")
@property
def last_name(self):
return self._data.get("last_name", "")
@property
def gender(self):
return self._data.get("gender", "")
@property
def date_of_birth(self):
return self._data.get("date_of_birth", "")
@property
def nationality(self):
return self._data.get("nationality", "")
In the above employee.py file, we have two levels of abstraction,
Employee and EmployeeInfo (both classes are in the same python module).
The Employee class encapsulates the logic for loading the JSON file and retrieving
the details of the employee corresponding to the employee ID supplied during object
instantiation.
The EmployeeInfo class has a bunch of property or getters, corresponding to employee
attributes in JSON record (e.g. first_name, last_name, gender etc).
Now let’s access the actual employee data from JSON file. I am going to run python interpreter in interactive mode,
~$ python3 -i employee.py
>>> emp1 = Employee("1") # Creating instance of first employee
>>> emp1.info.first_name
'David'
>>> emp1.info.last_name
'Brown'
>>> emp1.info.gender
'Male'
>>>
>>> emp2 = Employee("2") # Creating instance of second employee
>>> emp2.info.first_name
'Laura'
>>> emp2.info.last_name
'White'
>>> emp2.info.date_of_birth
'1993-05-17'
>>> emp2.info.nationality
'United States'
>>>
Alternate Approach: Dynamic Attribute Access Using __getattr__ (hack)
The EmployeeInfo class, has five different property or getter methods, one for each
employee info filed. If you feel that it’s kind of boiler-plate code with many getter methods,
you can use the magic of __getattr__ method.
class EmployeeInfo:
def __init__(self, data):
self._data = data
def __getattr__(self, name):
if name not in self._data.keys():
raise AttributeError(f"Employee has not attribute {name}")
return self._data.get(name)
In the above code, when we try to access an attribute on EmployeeInfo object by saying,
>>> emp1 = Employee("1")
>>> emp1.info.first_name # we are doing an attribute look-up on EmployeeInfo object
Here the name of the attribute that we are trying to do a look-up is first_name, which
obviously does not exist on EmployeeInfo object itself (The only instance attribute that
EmployeeInfo has is _data). Since we are trying to access a missing attribute on
EmployeeInfo object, __getattr__ method gets automatically called for missing attributes and
the name the missing attribute is passed-in as a string to __getattr__ method and that string
is collected by parameter name.
In __getattr__ method we are validating if the attribute for which we are trying to get the value,
in this case first_name is present as key of the dictionary self._data. If it is present
then we are doing a dictionary look-up and returning the value of key first_name.
The same process happens for other employee attributes are well.
Back to Articles