zoukankan      html  css  js  c++  java
  • Python解析JSON为实体

    前几天有同事问如何将一个json字符串反序列化为实体,当时只是简单找了一下方案,并未对这个事情做深入的了解。一致感觉这个挺有意思于是今晚就搜索了一些资料并作了测试,感兴趣的同学可以进一步深入料及。总而,感觉python的就是可以写很少代码,引入一些现有包就可以轻易实现自己想要的功能。

    单层实体:

    自定义一个单层实体公共类JsonClass.py:

    #!/usr/bin/python
    import json
    
    class JsonClass(object):
        def to_json_string(self):
            return json.dumps(self, default=lambda obj: obj.__dict__)
    
        def from_json_string(self, json_string):
            data = json.loads(json_string)
            for key in self.__dict__.keys():
                setattr(self, key, data[key])

    根据自己的需要反序列化的json字符串定义实体:

    {"timestamp": 1560948789.5293133, "name": "a", "id": 1}

    自定义实体Task.py

    from com.dx.test.JsonClass import JsonClass
    
    class Task(JsonClass):
        def __init__(self, id=None, name=None, timestamp=None):
            self.id = id
            self.name = name
            self.timestamp = timestamp

    测试类TaskTest.py

    #!/usr/bin/python
    import time
    from com.dx.test.Task import Task
    
    if __name__ == '__main__':
        # 序列化
        task = Task(1, "a", time.time())
        print(task.to_json_string())
    
        # 反序列化
        json_string = '{"timestamp": 1560948789.5293133, "name": "a", "id": 1}'
        task = Task()
        task.from_json_string(json_string)
        print(task.id)

    Debug后截图效果:

    多层实体:

    方案一(采用自定函数解析实体):

    自定义json_deserialize函数实现多层解析:

    import json
    
    def json_deserialize(json_data, obj):
        py_data = json.loads(json_data)
        dic2class(py_data, obj)
    
    
    '''
    Dict convert to Class
    通过setattr函数赋值属性,如果有值就赋值属性和值
    '''
    def dic2class(py_data, obj):
        for name in [name for name in dir(obj) if not name.startswith('_')]:
            if name not in py_data:
                setattr(obj, name, None)
            else:
                value = getattr(obj, name)
                setattr(obj, name, set_value(value, py_data[name]))
    
    
    
    '''
    设置虚拟类属性值
    '''
    def set_value(value, py_data):
        if str(type(value)).__contains__('.'):
            # value 为自定义类
            dic2class(py_data, value)
        elif str(type(value)) == "<class 'list'>":
            # value为列表
            if value.__len__() == 0:
                # value列表中没有元素,无法确认类型
                value = py_data
            else:
                # value列表中有元素,以第一个元素类型为准
                child_value_type = type(value[0])
                value.clear()
                for child_py_data in py_data:
                    child_value = child_value_type()
                    child_value = set_value(child_value, child_py_data)
                    value.append(child_value)
        else:
            value = py_data
        return value

    根据自己json字符串自定义实体:

    class Meta:
        currentPage = 0
        pageSize = 0
        realSize = 0
        startIndex = 0
        totalCount = 0
        totalPages = 0
    
    
    class Data:
        centerCode = ""
        centerName = ""
        createTime = ""
        createUser = ""
        createUserId = ""
        districtCode = ""
        districtName = ""
        groupCode = ""
        groupName = ""
        id = 0
        latitude = ""
        longitude = ""
        plazaCode = ""
        plazaName = ""
        tenantId = ""
        updateTime = ""
        updateUser = ""
        updateUserId = ""
        version = 0
    
    
    class Result:
        data = [Data()]
        message = ""
        meta = Meta()
        status = 0

    解析实体测试类:

    #!/usr/bin/python
    
    import requests
    import json
    from com.dx.test.SelfDefParseJson import json_deserialize
    from com.dx.test.Result import Result
    
    url = "http://wdspinspector.intra.uat.beyonds.gw/phoenix/inspector/v1/baseinfos";
    headers = {
        "tenantId": "xx",
    }
    params = {
        "p": 1,
        "ps": 20,
        "groupCode": "xx"
    }
    response = requests.get(url, params=params, headers=headers)
    responseJsonFormat = json.dumps(response.json(), sort_keys=True, indent=4, separators=(',', ': '))
    
    result = Result()
    json_deserialize(responseJsonFormat, result)

    Debug效果

    方案二(安装from addict import Dict,任何层json都可以反序列化):

    这种方式比较简单,只需要安装addict包。

    Installing

    You can install via pip

    pip install addict

    or through conda

    conda install addict -c conda-forge

    Addict runs on Python 2 and Python 3, and every build is tested towards 2.7, 3.6 and 3.7.

    测试代码:

    #!/usr/bin/python
    
    import requests
    import json
    from com.dx.test.Result import Result
    from addict import Dict
    
    url = "http://xxx/xx/xx";
    headers = {
        "tenantId": "xx",
    }
    params = {
        "p": 1,
        "ps": 20,
        "groupCode": "xx"
    }
    response = requests.get(url, params=params, headers=headers)
    
    dict = Dict(response.json())
    print(dict.data[0].plazaName)
    print(dict.meta.totalCount)

    Debug效果

  • 相关阅读:
    jQuery笔记(1)
    [bzoj 1878][SDOI2009]HH的项链
    [bzoj 1968][Ahoi2005]COMMON 约数研究
    [bzoj 1899][ZJOI2004]lunch 午餐
    [bzoj 1090][SCOI2003]字符串折叠
    CodeForces 1029E div3
    [bzoj 1270][BeijingWc2008]雷涛的小猫
    [bzoj 1260][CQOI 2007]涂色paint
    [AtCoder ARC101D/ABC107D] Median of Medians
    [luogu 1070]道路游戏(NOIP2009T4)
  • 原文地址:https://www.cnblogs.com/yy3b2007com/p/13991469.html
Copyright © 2011-2022 走看看