首页 > 编程语言 >【Python】操作复杂嵌套的json数据

【Python】操作复杂嵌套的json数据

时间:2023-04-25 15:55:43浏览次数:44  
标签:__ Python self labor 嵌套 json key tools

1、相关文章

递归获取所有key-value值:https://www.cnblogs.com/phoenixy/p/17126455.html

 

2、对复杂的json进行增删改查

① 获取数据

# -*- coding: UTF-8 -*-
import json
from jsonpath_ng import parse
from aa_demo.base.logger import *


class json_labor_tools:
    """
    操作Json对象
    注意事项:
        1.不同层级同名key的value均会被修改, 如果修改单独的key 需要指定层级
        2。属性访问的时候,对json节点名称有比较高的要求
    """

    def __init__(self, buffer: dict = None):
        """

        :param buffer: 固有的属性, 访问不存在的属性时自动访问此属性
        """
        self._buffer = buffer

    def __getitem__(self, key):
        """ getitem复写 实现下标的访问"""
        return self.get(key)

    def __getattr__(self, key):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            return super().__getattr__(key)

        return self.get(key)

    def get(self, key: str, num=0):
        """

        :param key: 需要获取的key, 如果存在同名的key取第一个值
        :param num: 0 取首个数据值, -1 取全部数据值 (当num个数大于列表内容相当于=0))
        :return:
        """

        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key
        ret = []
        for match in parse(condition).find(self.__dict__['_buffer']):
            ret.append(match.value)

        if not ret:
            logs.error("key: {} 不存在, 请检查参数或文件内~".format(key))
        else:
            return ret if num == -1 else ret[num] if 0 < num < len(ret) else ret[0]


if __name__ == "__main__":
    """run"""
    j = json.load(open('../data/demo/demo.json'))
    logs.debug("json 原文件内容: {}".format(j))
    logs.debug("="*80 + "\n")

    """获取复杂json的key-value"""
    logs.debug("下标获取:{}".format(json_labor_tools(j)['addr9']))
    logs.debug("属性访问:{}".format(json_labor_tools(j).addr8))
    logs.debug("方法获取:{}".format(json_labor_tools(j).get('addr7')))
    logs.debug("方法获取多个:{}".format(json_labor_tools(j).get('listAddr', -1)))

    """保存文件"""
    # json.dump(j, open('../data/demo/demo.json', 'w+'), ensure_ascii=False, indent=4, sort_keys=True)

    logs.debug("="*80 + "\n")
    logs.debug("json 新文件内容: {}".format(j))

 

执行结果:

 

 ② 修改数据

# -*- coding: UTF-8 -*-
import json
from jsonpath_ng import parse
from aa_demo.base.logger import *


class json_labor_tools:
    """
    操作Json对象
    注意事项:
        1.不同层级同名key的value均会被修改, 如果修改单独的key 需要指定层级
        2。属性访问的时候,对json节点名称有比较高的要求
    """

    def __init__(self, buffer: dict = None):
        """

        :param buffer: 固有的属性, 访问不存在的属性时自动访问此属性
        """
        self._buffer = buffer

    def __setitem__(self, key, value):
        """ etitem复写 实现下标的访问"""
        return self.set(key, value)

    def __setattr__(self, key: str, value):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            super().__setattr__(key, value)
            return
        else:
            self.set(key, value)

    def set(self, key: str, value):
        """

        :param key: 需要修改的key, 如果存在同名的key 修改全部
        :param value: 修改后的内容
        :return:
        """
        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key

        parse(condition).update(self.__dict__['_buffer'], value)
        return self


if __name__ == "__main__":
    """run"""
    j = json.load(open('../data/demo/demo.json'))
    logs.debug("json 原文件内容: {}".format(j))
    logs.debug("="*80 + "\n")

    """修改复杂json的key-value"""
    json_labor_tools(j)["adminAddr"] = "修改后的地址"
    json_labor_tools(j)["listAddr"] = "set-listAddr"
    json_labor_tools(j).listName = "修改后的名字"
    json_labor_tools(j).set("listAge", "110")
    json_labor_tools(j).set("listAge4", "不存在")

    """保存文件"""
    # json.dump(j, open('../data/demo/demo.json', 'w+'), ensure_ascii=False, indent=4, sort_keys=True)

    logs.debug("="*80 + "\n")
    logs.debug("json 新文件内容: {}".format(j))

 

 

执行结果

 

③ 删除数据

# -*- coding: UTF-8 -*-
import json
from jsonpath_ng import parse
from aa_demo.base.logger import *


class json_labor_tools:
    """
    操作Json对象
    注意事项:
        1.不同层级同名key的value均会被修改, 如果修改单独的key 需要指定层级
        2。属性访问的时候,对json节点名称有比较高的要求
    """

    def __init__(self, buffer: dict = None):
        """

        :param buffer: 固有的属性, 访问不存在的属性时自动访问此属性
        """
        self._buffer = buffer

    def __delattr__(self, key):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            return super().__getattr__(key)

        return self.pops(key)

    def pops(self, key: str):
        """

        :param key: 需要删除的key, 如果存在同名的key 删除全部
        :return:
        """
        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key

        ret = []
        for match in parse(condition).find(self.__dict__['_buffer']):
            ret.append(match.context.value)

        if not ret:
            logs.error("key: {} 不存在, 请检查参数或文件内~".format(key))
        else:
            for i in range(len(ret)):
                # ret[i].pop(key)
                del ret[i][key]

        return self


if __name__ == "__main__":
    """run"""
    j = json.load(open('../data/demo/demo.json'))
    logs.debug("json 原文件内容: {}".format(j))
    logs.debug("="*80 + "\n")

    """修改复杂json的key-value"""
    del json_labor_tools(j).adminAddr
    del json_labor_tools(j).addr1
    json_labor_tools(j).pops("adminTel").pops("addr2").pops("listAddr")

    """保存文件"""
    # json.dump(j, open('../data/demo/demo.json', 'w+'), ensure_ascii=False, indent=4, sort_keys=True)

    logs.debug("="*80 + "\n")
    logs.debug("json 新文件内容: {}".format(j))

 

执行结果

 

 

  

3、完整代码实现

# -*- coding: UTF-8 -*-
import json
from jsonpath_ng import parse
from aa_demo.base.logger import *


class json_labor_tools:
    """
    操作Json对象
    注意事项:
        1.不同层级同名key的value均会被修改, 如果修改单独的key 需要指定层级
        2。属性访问的时候,对json节点名称有比较高的要求
    """

    def __init__(self, buffer: dict = None):
        """

        :param buffer: 固有的属性, 访问不存在的属性时自动访问此属性
        """
        self._buffer = buffer

    def __getitem__(self, key):
        """ getitem复写 实现下标的访问"""
        return self.get(key)

    def __setitem__(self, key, value):
        """ etitem复写 实现下标的访问"""
        return self.set(key, value)

    def __getattr__(self, key):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            return super().__getattr__(key)

        return self.get(key)

    def __setattr__(self, key: str, value):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            super().__setattr__(key, value)
            return
        else:
            self.set(key, value)

    def __delattr__(self, key):
        """ 属性访问 节点名称需要符合json要求 """
        if key in self.__dir__() or key == '_buffer':
            return super().__getattr__(key)

        return self.pops(key)

    def get(self, key: str, num=0):
        """

        :param key: 需要获取的key, 如果存在同名的key取第一个值
        :param num: 0 取首个数据值, -1 取全部数据值 (当num个数大于列表内容相当于=0))
        :return:
        """

        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key
        ret = []
        for match in parse(condition).find(self.__dict__['_buffer']):
            ret.append(match.value)

        if not ret:
            logs.error("key: {} 不存在, 请检查参数或文件内~".format(key))
        else:
            return ret if num == -1 else ret[num] if 0 < num < len(ret) else ret[0]

    def set(self, key: str, value):
        """

        :param key: 需要修改的key, 如果存在同名的key 修改全部
        :param value: 修改后的内容
        :return:
        """
        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key

        parse(condition).update(self.__dict__['_buffer'], value)
        return self

    def pops(self, key: str):
        """

        :param key: 需要删除的key, 如果存在同名的key 删除全部
        :return:
        """
        if not key.startswith('$..'):
            condition = '$..' + key
        else:
            condition = key

        ret = []
        for match in parse(condition).find(self.__dict__['_buffer']):
            ret.append(match.context.value)

        if not ret:
            logs.error("key: {} 不存在, 请检查参数或文件内~".format(key))
        else:
            for i in range(len(ret)):
                # ret[i].pop(key)
                del ret[i][key]

        return self

    def add(self, items: dict = None):
        """

        :param items: 需要添加键值对
        :return:
        """
        if isinstance(items, dict) and not None:
            self.__dict__['_buffer'].update(items)
        else:
            logs.error("未添加成功,请检查item参数是否符合要求")

        return self


if __name__ == "__main__":
    """run"""
    j = json.load(open('../data/demo/demo.json'))
    logs.debug("json 原文件内容: {}".format(j))
    logs.debug("="*80 + "\n")

    # 获取value
    # logs.debug("获取到的 listAddr: {}".format(json_labor_tools(j).get("listAddr")))
    # logs.debug("获取到的全部 listAddr: {}".format(json_labor_tools(j).get("listAddr", -1)))
    # logs.debug("listAddr: {}".format(json_labor_tools(json_labor_tools(j).get('listbak')).get("listAddr")))
    # # 修改value
    # json_labor_tools(j).set("adminAddr", "qipan").
    # json_labor_tools(j).set("adminAddr", "tianjin").set("adminPhone", "15700010002")
    # json_labor_tools(j).set("adminAge", "32").set("list", [1, 2, 3, 4, 4, 6])
    # # 添加key-value
    # json_labor_tools(j).add({"listadd": "add"})
    # json_labor_tools(j).add({"listadd": ["add", "add2"]}).add({"name": "add"})
    # json_labor_tools(json_labor_tools(j).get('listbak')).set("listAge", 32)
    # # 删除key-value
    # json_labor_tools(j).pops('listAddr')
    json_labor_tools(j).set("adminAge", "30").add({"addAdminName": "addVlue"}).pops("addr1")

    # # getitem和setitem复写, 下标访问
    # logs.debug("获取 adminAge = {}".format(json_labor_tools(j)['adminAge']))
    # logs.debug("获取 listTel = {}".format(json_labor_tools(j)['listTel']))

    # 属性访问及修改内容 不指定层级会修改全部同名key的value
    # logs.debug("获取到的 adminAddr: {}".format(json_labor_tools(j).adminAddra))
    logs.debug("获取到的 listName: {}".format(json_labor_tools(j).listName))
    json_labor_tools(j).adminPhone = "13612340000"
    # json_labor_tools(json_labor_tools(j).listbak[0]).listPhone = '13212348877'
    # del json_labor_tools(j).adminAddr
    del json_labor_tools(j).listAddr

    """保存文件"""
    # json.dump(j, open('../data/demo/demo.json', 'w+'), ensure_ascii=False, indent=4, sort_keys=True)

    logs.debug("="*80 + "\n")
    logs.debug("json 新文件内容: {}".format(j))

 

 

执行结果

 

 

 

 

参考地址:https://www.jianshu.com/p/e6fb96b6288e

标签:__,Python,self,labor,嵌套,json,key,tools
From: https://www.cnblogs.com/phoenixy/p/17352757.html

相关文章

  • Python语言学习讲解十六:python之描述符__set__和__get__ 等解释
    一、方法:首先说下python中存在的几种方法:对象方法、静态方法、类方法等,归属权分别为obj、cls、cls其实可以从他们的参数中就可以看的出来对象方法参数中含有self,这个类似于C++中的this指针。静态方法使用@staticmethod来修饰,可以通过类或类的实例对象来调用而已.1.>>>class2.......
  • Python语言学习讲解十九: 异常信息的详细获取
    由于近期忙着手游发布,所以这几天没有及时更新望各位学者见谅。年底了,各大公司特别是游戏行业都着手赶年底末班车,给用户一个新年的礼物。在项目中出现了一些异常日志,但是并没有记录到详细的错误信息。特别是报错在哪一个文件哪一行等信息。[python] viewplain ......
  • python读取文件创建时间
    #获取文件时间(浮点数格式)csv_time=os.path.getmtime("C:/Users/DELL/Desktop/20000/allqueryCommodity.csv")print("csv_time",csv_time)#结果:1682402963.033327#把浮点数格式格式转成格式化格式local_time=time.localtime(csv_time)print("local_time",local_tim......
  • Python中的时间格式的读取与转换(time模块)
    一、时间的表示格式在Python中,表示时间的格式有4种较为常用,分别是浮点数格式、标准可读格式、格式化格式以及自定义格式。(名字是自己起的,非官方命名)(1)浮点数格式用一个float格式的浮点数表示时间,其具体含义表示为从世界标准纪元时间(1970年1月1日)起算至该时间节点的秒数。(2)标准......
  • Python tkinter界面
    #文档C:/Users/Administrator/AppData/Local/Programs/Python/Python311/Doc/html/library/tk.html#TIP:如果不想要cmd,扩展名py改为pywfromtkinterimport*fromtkinter.ttkimport*#窗口tk=Tk()tk.title("联安通达audio/default.ini配置工具V0.0.1")tk.geom......
  • (完结篇)Python web框架FastAPI——一个比Flask和Tornada更高性能的API 框架
    今日鸡汤借问酒家何处有,牧童遥指杏花村。0前言    前几天给大家分别分享了(入门篇)简析Pythonweb框架FastAPI——一个比Flask和Tornada更高性能的API框架和(进阶篇)Pythonweb框架FastAPI——一个比Flask和Tornada更高性能的API框架。今天欢迎大家来到FastAPI系列分享的完结篇......
  • python 修改服务器网卡信息
    importosimportreimportnetifacesimportsubprocessclassNetWorkConfig:def__init__(self):pass@staticmethoddefcheck_network_isvalid(ip,netmask,gateway,dns):"""判断用户输入的网络配置是否可用:pa......
  • python 相关
    python判断文件是否存在os.path.exists(file_path):python多线程p1=threading.Thread(target=down)t1=threading.Thread(target=crawl)print("启动")p1.start()t1.start()print("join")p1.join()t1.join()python多线程与redis控制多线程的数量whileTr......
  • python编程基础
    Python并不是一门新的编程语言,1991年就发行了第一个版本,2010年以后随着大数据和人工智能的兴起,Python又重新焕发出了耀眼的光芒。在2019年12月份世界编程语言排行榜中,Python排名第三,仅次于Java和C语言。Python是一门开源免费的脚本编程语言,它不仅简单易用,而且功能强大......
  • 分享Python采集88个NET电子商务源码,总有一款适合您
    Python采集的88个NET电子商务源码下载链接:百度网盘请输入提取码 提取码:c0gh编辑众筹系统(RaiseDreams众筹梦想)V2.1.6云点滴客户关系管理CRMOA系统V1.02.13云点滴客户解决方案V1.0.0创想商务B2B网站管理系统V3.1冰兔(Btoo)网店系统V6.39ASP.NET4.0电子商城MVC+EF水果市场2......