I have JSON data as follows:
{
"Address": {
"House_Number": 2,
"State": "MA",
"Street_Number": 13
},
"Name": "John"
}
I want to load it into a class defined as follows:
class Address:
def __init__(self):
self.House_Number = 0
class Employee:
def __init__(self):
self.Name = ''
self.Address = Address()
If I use the class Employee
as object_hook
, then it uses the same class for both the objects (the outer object having Name
and Address
as members and inner object having members House_Number
etc.).
Basically, if e
is the object in which the JSON data has been loaded, then
type(e.Address)
should be Address
not Employee
.
Is there any way to load this JSON data into Employee
class maintaining the class hierarchy? The hierarchy can be arbitrarily deep.
To deserialize the string to a class object, you need to write a custom method to construct the object. You can add a static method to ImageLabelCollection inside of which you construct Label objects from the loaded JSON dictionary and then assign them as a list to the class variable bbox.
Use pd. read_json() to load simple JSONs and pd. json_normalize() to load nested JSONs. You can easily access values in your JSON file by chaining together the key names and/or indices.
You can identify objects by looking at their keys. You can then map them to the appropriate class.
Using your example data:
class AddressClass:
# The parameters to init needs to be the same as the json keys
def __init__(self, House_Number, Street_Number, State):
self.house_number = House_Number
self.street_number = Street_Number
self.state = State
class EmployeeClass:
# Same here
def __init__(self, Name, Address):
self.name = Name
self.address = Address
# Map keys to classes
mapping = {frozenset(('House_Number',
'Street_Number',
'State')): AddressClass,
frozenset(('Name',
'Address')): EmployeeClass}
Then, create a function that converts a dictionary to an appropriate python class.
This will be passed to json.load
as object_hook
:
def class_mapper(d):
return mapping[frozenset(d.keys())](**d)
Above, frozenset
is used because dict keys in the json are unordered (hence the set) and the dict keys in the mapping needs to be hashable (hence "frozen").
Finally, parse the json with the class_mapper
function as object_hook
:
j = '''
{
"Address": {
"House_Number": 2,
"State": "MA",
"Street_Number": 13
},
"Name": "John"
}
'''
employee = json.loads(j, object_hook=class_mapper)
print(employee.name,
employee.address.house_number,
employee.address.street_number,
employee.address.state)
# John 2 13 MA
If your json data have optional keys, you can create a more robust class_mapper
, although it may be slightly slower. You also need to add default values to the class constructor parameters that are optional.
def class_mapper(d):
for keys, cls in mapping.items():
if keys.issuperset(d.keys()):
return cls(**d)
else:
# Raise exception instead of silently returning None
raise ValueError('Unable to find a matching class for object: {!s}'.format(d))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With