我有如下JSON数据:
{ "Address": { "House_Number": 2, "State": "MA", "Street_Number": 13 }, "Name": "John" }
我想将它加载到如下定义的类中:
class Address: def __init__(self): self.House_Number = 0 class Employee: def __init__(self): self.Name = '' self.Address = Address()
如果我使用类Employee
如object_hook
,然后它使用两个物体的相同类(具有外部对象Name
和Address
作为成员和内部具有对象成员House_Number
等).
基本上,如果e
是加载JSON数据的对象,那么
type(e.Address)
应该Address
不是Employee
.
有没有办法将这个JSON数据加载到Employee
维护类层次结构的类中?层次结构可以任意深入.
您可以通过查看其键来识别对象.然后,您可以将它们映射到适当的类.
使用您的示例数据:
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
使用是因为json中的dict键是无序的(因此是集合)并且映射中的dict键需要是可散列的(因此"冻结").
最后,使用以下class_mapper
函数解析json 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))