专栏首页授客的专栏Python_实现json数据的jsonPath(精简版)定位及增删改操作

Python_实现json数据的jsonPath(精简版)定位及增删改操作

实践环境

win7 64

Python 3.4.0

代码

#-*- encoding:utf-8 -*-

# author:授客

import re

def parse_sub_expr(sub_expr):

'''

解析字表达式-元素路径的组成部分

:param sub_expr:

:return:

'''

RIGHT_INDEX_DEFAULT = '200000000' # 右侧索引的默认值 未指定右侧索引时使用,形如 key[2:]、key[:]

result = re.findall('\[.+\]', sub_expr)

if result: # 如果子表达式为数组,形如 [1]、key[1]、 key[1:2]、 key[2:]、 key[:3]、key[:]

array_part = result[0]

array_part = array_part.lstrip('[').rstrip(']')

key_part = sub_expr[:sub_expr.index('[')]

if key_part == '$': # 如果key为 $ ,为根,替换为数据变量 json_data

key_part = JSON_DATA_VARNAME

elif key_part == '*':

key_part == '\[.+\]' # 如果key为 * ,替换为 \[\.+\] 以便匹配 ["key1"]、["key2"]、……

else:

key_part = '\["%s"\]' % key_part

if array_part == '*': # 如果数组索引为 * ,替换为 \[\d+\] 以便匹配 [0]、[1]、……

array_part = '\[\d+\]'

else:

array_part_list = array_part.replace(' ', '').split(':')

left_index = array_part_list[0:1]

right_index = array_part_list[1:]

if left_index:

left_index = left_index[0]

if not (left_index or left_index.isdigit()): # 为空字符串、非数字

left_index = '0'

else:

left_index = '0'

if right_index:

right_index = right_index[0]

if not (right_index or right_index.isdigit()):

right_index = RIGHT_INDEX_DEFAULT # 一个比较大的值,

array_part = left_index + '-' + right_index

else:

array_part = left_index

array_part = '\[[%s]\]' % array_part # 数组索引设置为 \[[n-m]\],以便匹配[n],[n+1], ……,[m-1]

return key_part + array_part

elif sub_expr == '*':

sub_expr = '\[.+\]'

elif sub_expr == '$':

sub_expr = JSON_DATA_VARNAME

else:

sub_expr = '\["%s"\]' % sub_expr

return sub_expr

def parse_json(json_data, data_struct_link):

'''

递归解析json数据结构,存储元素的路径

:param json_data:

:param data_struct_link:

:return:

'''

if type(json_data) == type({}): # 字典类型

keys_list = json_data.keys()

for key in keys_list:

temp_data_struct_link = data_struct_link + '["%s"]' % key

if type(json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典

data_struct_list.append(temp_data_struct_link)

else:

parse_json(json_data[key], temp_data_struct_link)

elif type(json_data) == type([]): # 数组类型

array_length = len(json_data)

for index in range(0, array_length):

temp_json_data = json_data[index]

keys_list = temp_json_data.keys()

for key in keys_list:

temp_data_struct_link = data_struct_link + '[%s]["%s"]' % (str(index), key)

if type(temp_json_data[key]) not in [type({}), type([])]: # key对应的value值既不是数组,也不是字典

data_struct_list.append(temp_data_struct_link)

else:

parse_json(temp_json_data[key], temp_data_struct_link)

if __name__ == '__main__':

json_data = [{"data": [{

"admin": "string|集群负责人|||",

"components": [

{

"clusterId": "integer|组件所属的集群 id|||",

"createTime": "string|组件创建时间|||",

"description": "string|组件描述|||",

"enabled": "boolean|组件是否开启||false|",

},

{

"clusterId": "integer|组件所属的集群 id|||",

"createTime": "string|组件创建时间|||",

"description": "string|组件描述|||",

"enabled": "boolean|组件是否开启||false|",

}

],

"createTime": "string|集群创建时间|||",

"description": "string|集群描述|||",

"enabled": "boolean|集群是否开启||false|",

"id": "integer|集群 id|||",

"modifyTime": "string|集群修改时间|||",

"name": "string|集群名|||"

}],

"errMsg": "string||||",

"ok": "boolean||||",

"status": "integer||||"

}]

JSON_DATA_VARNAME = 'json_data' # 存在json数据的变量名称

data_struct_list = [] # 用于存放所有 json 元素路径,形如 json_data[0]["data"][0]["components"][0]["enabled"]

data_struct_link = 'json_data' # 用于临时存放单条json 元素路径(的一部分)

parse_json(json_data, data_struct_link)

print('获取的json元素路径,元素值如下:')

for item in data_struct_list:

print(item, '\t', eval(item))

# 测试用表达式

# expr = '$.data[*].components[0]' # json数据为字典 形如 {……}

# expr = '$[*].data[0:1].components[*]' # json数据为数组 形如 [{……}]

expr = 'data[0:1].components[*]'

# expr = 'data[0:1].components'

# 解析表达式为正则表达式

re_pattern = ''

for sub_expr in expr.split('.'):

re_pattern += parse_sub_expr(sub_expr)

print('\n元素路径jsonpath表达式为:%s' % expr)

print('元素路径正则表达式re pattern为:%s' % re_pattern)

print('\njsonpath 匹配结果如下:')

re_pattern = re.compile(re_pattern)

target_set = set() # 匹配结果会有重复值,所以采用集合

for item in data_struct_list:

results = re.findall(re_pattern, item)

for result in results:

print('匹配的元素路径jsonpath为:%s' % item)

print('正则匹配结果为:%s' % result)

target = item[0:item.index(result) + len(result)]

print('供提取数据使用的jsonpath为:%s' % target)

print('提取的结果值为:%s \n' % eval(target))

target_set.add(target)

# 通过匹配提取的目标结果,操作json串

for item in target_set:

target = eval(item)

if type(target) == type({}): # 如果为字典

# 更改键的值

target['clusterId'] = 10

# 新增键值对

target['new_key'] = 'key_value'

# 更改键的名称,可以考虑先复制旧的键值,赋值给新的键,然后删除旧的键

target['description_new'] = target['description']

# 删除键值对

del target['description']

elif type(target) == type([]):

# 暂不实现

pass

print(json_data)

运行结果截图:

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • JMeter 线程组之ConcurrencyThreadGroup介绍

    https://pan.baidu.com/s/14yHUKvH9M33k25EZRPnBjA

    授客
  • JMeter JMeter远程分布式联机性能测试

    当一个JMeter客户端因网络限制等因素,无法模拟足够的用户对服务器施压时,需要用到JMeter分布式测试:用一台控制机,控制多台远程负载机,同时对服务器施压...

    授客
  • JQuery Deferred对象使用小结

    如下,打开页面时,获取默认选中的项目,同时也会初始化Combobox下拉框下拉列表数据

    授客
  • 基于 HTML5 结合互联网+ 的 3D 隧道

    目前,物资采购和人力成本是隧道业发展的两大瓶颈。比如依靠民间借贷,融资成本很高;采购价格不透明,没有增值税发票;还有项目管控和供应链管理的问题。成本在不断上升,...

    HT_hightopo
  • 机器学习(二) 如何做到Kaggle排名前2%

    Jason Guo
  • jquery.ajax()怎么把获取来的内容转为JSON,并使用。

    现在越来越多的接口调用返回的数据类型为json数据类型,所以我们在写网页的时候通过AJAX调用数据的话可以通过设置JQ的属性

    睿儿网络郝刚
  • py-ops面向编程的关键字测试框架

    这是一款基于pytest封装,同时支持关键字和BDD,测试数据分离,面向编程,轻量级的,对上层自动化应用友好的基础测试框架。

    上帝De助手
  • 解决echarts中饼图标签重叠的问题

    avoidLabelOverlap:是否启用防止标签重叠策略,默认开启,在标签拥挤重叠的情况下会挪动各个标签的位置,防止标签间的重叠。

    砸漏
  • 基于百度翻译的简单爬虫翻译-- coding:utf-8 --访问网址模拟浏览器创建文件夹用一个text文件保存,文件名用单词名字

    因为最近有数据需求,自己写了一个简单的小爬虫,但是这是第一版还是比较简陋,慢慢更新吧. ---- 能够实现的功能是查询英语单词和中文单词并且能够找出读音来,希望...

    云时之间
  • zookeeper入门

    Apache ZooKeeper是Apache软件基金会的一个软件项目,他为大型分布式计算提供开源的分布式配置服务、同步服务和命名注册。ZooKeeper曾经是...

    LiosWong

扫码关注云+社区

领取腾讯云代金券