Python_實現json數據的jsonPath(精簡版)定位及增刪改操作


基於python實現json數據的jsonPath(精簡版)定位及增刪改操作

 

by:授客 QQ1033553122

 

 

實踐環境

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)

 

運行結果截圖:

Python_實現json數據的jsonPath(精簡版)定位及增刪改操作

 

 

 

 

 

 

 



Python_實現json數據的jsonPath(精簡版)定位及增刪改操作

Python_實現json數據的jsonPath(精簡版)定位及增刪改操作

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM