Ответ 1
Вы можете идентифицировать объекты, просматривая их ключи. Затем вы можете сопоставить их с соответствующим классом.
Используя данные примера:
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}
Затем создайте функцию, которая преобразует словарь в соответствующий класс python.
Это будет передано json.load
как object_hook
:
def class_mapper(d):
return mapping[frozenset(d.keys())](**d)
Выше, frozenset
используется, потому что ключи dict в json неупорядочены (следовательно, набор), а клавиши dict в сопоставлении должны быть хешируемыми (следовательно, "замороженными" ).
Наконец, проанализируйте json с помощью функции class_mapper
как 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
Дополнения
Если ваши json-данные имеют необязательные ключи, вы можете создать более надежный class_mapper
, хотя он может быть немного медленнее. Вам также необходимо добавить значения по умолчанию к параметрам конструктора классов, которые являются необязательными.
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))