如何将JSON数据加载到嵌套类中?

 liujiayan0529_584 发布于 2022-12-10 13:22

我有如下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()

如果我使用类Employeeobject_hook,然后它使用两个物体的相同类(具有外部对象NameAddress作为成员和内部具有对象成员House_Number等).

基本上,如果e是加载JSON数据的对象,那么 type(e.Address)应该Address不是Employee.

有没有办法将这个JSON数据加载到Employee维护类层次结构的类中?层次结构可以任意深入.

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.loadobject_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))
    

    2022-12-11 02:06 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有