• 指定json的某个节点进行增、删、改


    有时候我们需要对json结构的数据进行更新,或增,或改,或删。
    当json层级比较复杂时操作起来是比较麻烦的,得一层层找下去找到要更新的节点才能操作它。
    我用python语言封装了一个类,提供三个函数分别用于增删改json的目标节点。

    首先我们先确定什么是路径(path);
    如json:
    dataA={“code”: 0,
    “data”: {“areaCode”: “86”, “avatar”: “”, “countryCode”: “86”, “customer_risk_type”: “0”,
    “customer”:{“name”:“syc”,“sex”:“m”}},
    “valuelist”:[{“expiration”: 1578043337756, “extendStatusBit”: 1, “firstLogin”: “True”, “id”: 11529},
    {“expiration”: 1578043337757, “extendStatusBit”: 2, “firstLogin”: “True”, “id”: 11539,
    “transaction”:[{“stockcode”:“601235”},{“price”:2.12}]},
    {“expiration”: 1578043337758, “extendStatusBit”: 3, “firstLogin”: “True”, “id”: 11549},
    {“expiration”: 1578043337759, “extendStatusBit”: 4, “firstLogin”: “True”, “id”: 11559}],
    “msg”: “成功”}
    对于以上json,我们需要操作data下customer中的name,则name的路径为:/data/customer/name;
    再如:列表valuelist下第二个元素中transaction列表下的stockcode,则stockcode的路径为:
    /valuelist/(int)1/transaction/(int)0/stockcode

    **说明:**由于json允许用字符串类型的数字做key,所以当需要表示列表中第几个元素时前面加个(int)标识;
    1、增

    def addkv(self,data,path,key=None,value=None):
    """
    for example addkv(dataA,'/data/customer','age',30)
    :param data: Target JSON
    :param path:Location of new field,as '/data/customer'
    :param key: new field
    :param value:new field value
    :return:Added JSON
    1
    2
    3
    4
    5
    6
    7
    8
    :param data:目标JSON
    :param path:目标节点的路径,如 '/data/customer',/valuelist/(int)1/transaction/(int)0
    :param key: 在该节点下新增的键
    :param value:在该节点下新增的键对应的值
    :return:新增键值完成后的json

    1
    2
    3
    4
    5
    6
    注意:如果目标节点不是字典类型程序会报错,即路径最后一个节点比如/data/customer中的customer的类型必须是字典;

    2、删

    def delete(self,data,path):
    """
    Delete the node of the specified path
    :param data:Target JSON
    :param path:path
    :return:JSON after deleting a node
    1
    2
    3
    4
    5
    6
    :param data:目标JSON
    :param path:路径
    :return:删除节点后返回的json
    1
    2
    3
    3、改

    def update(self,data,path,newvalue):
    """
    Update JSON
    :param data:Target JSON
    :param path:Route as '/valuelist/(int)0/expiration'
    :param newvalue:Modified value
    :return:Updated JSON
    1
    2
    3
    4
    5
    6
    7
    :param data:目标json
    :param path:路径
    :param newvalue:要改为的新值
    :return:返回更新后的json
    1
    2
    3
    4
    完整代码如下:

    #!/usr/bin/env python
    #-*- coding:utf-8 -*-
    """
    解析json
    """
    class rcjson(object):

    def resolution(self,local={}):
    """
    解析json串中各个字段
    :param local:
    :return: [{'path': '/code', 'value': 0}, {'path': '/msg', 'value': 'ok'},.........]
    """
    def recursive_diff(l,res, path='/'):

    delim = '/' if path!= '/' else ''
    if(isinstance(l, dict)):
    iterl=l.keys()
    for k in iterl:
    v=l.get(k)
    new_path = delim.join([path, k])
    recursive_diff(v, res, new_path)
    elif(isinstance(l, list)):
    enum=enumerate(l, start=0)
    for i, item in enum:
    new_path = delim.join([path, '(int)'+str(i)])
    recursive_diff(item, res, new_path)
    else:
    res.append({
    'path': path,
    'value': l
    })
    result = []
    recursive_diff(local, result)
    return result

    def pathlist(self,paths):
    """
    将json节点路径由/../.../转变为list
    :param paths:[{'path': '/code', 'value': 0}, {'path': '/msg', 'value': 'ok'},.........]
    :return:[{'path': ['code'], 'value': 0}, {'path': ['data', 'areaCode'], 'value': '86'}, {'path': ['data', 'avatar'], 'value': ''},.....]
    """
    for path in paths:
    routes=path.get('path').split("/")[1:]
    newroutes=[]
    for route in routes:
    if('(int)' in route):
    start_loc = route.find('(int)')
    len_int=len('(int)')
    res_str = route[start_loc+len_int:]
    newroutes.append(int(res_str))
    else:
    newroutes.append(route)
    path['path']=newroutes
    return paths

    def updateValue(self,data,path,newvalue):
    """
    修改json中指定的字段的值
    :param data:目标json
    :param path: '/valuelist/(int)0/expiration' 路径
    :param newvalue:修改后的值
    :return:[] 或 [{'path': ['code'], 'value': 0}, {'path': ['data', 'areaCode'], 'value': '86'}, {'path': ['data', 'avatar'], 'value': ''},.....]
    """
    if(type(data)==dict):
    resultStr=self.resolution(data)
    index=-1
    for pathdic in resultStr:
    index=index+1
    p=pathdic.get("path")
    firstStr=path[:1]
    if(firstStr=="/"):
    if(p==path):
    pathdic["value"]=newvalue
    break
    else:
    if(p=="/"+path):
    pathdic["value"] = newvalue
    break
    if (index + 1 == len(resultStr)):
    return [] #没有找到匹配的路径
    resultList = self.pathlist(resultStr)
    return resultList
    else:
    return []

    def composeDict(self,gkey,result,pv,path,start,end):
    """
    组装只有字典的链路
    :param gkey: globals对象
    :param result: 字典
    :param pv: 字典 {'path': ['data', 'customer', 'sex'], 'value': 'm'}
    :param path: 列表 ['data', 'customer', 'sex']
    :param start:
    :param end:
    :return:
    """
    if (self.isExtend(result, path[0]) == False):
    gkey[path[0]] = {}
    result[path[0]] = gkey[path[0]]
    for i in range(start,end):
    dict_i1=gkey[path[i - 1]]
    pi=path[i]
    flag=self.isExtend(dict_i1,pi)
    if(flag== False):
    gkey[pi] = {}
    dict_i1[pi] = gkey[pi]
    lastkey = path[end] # 最后一个key
    key_1 = path[end-1] # 倒数第二个key
    gkey[key_1][lastkey] = pv.get("value")
    return result

    def composeJSON(self,resultlist):
    """
    组装JSON
    :param resultlist: [{'path': ['code'], 'value': 0}, {'path': ['data', 'areaCode'], 'value': '86'}, {'path': ['data', 'avatar'], 'value': ''},......]
    :return:json,list也当作json处理先
    """
    result={}
    gkey=globals()
    for pv in resultlist:
    path=pv.get('path') #list type ['data', 'areaCode']
    if(len(path)==1):
    value=pv.get('value')
    result[path[0]]=value
    elif(len(path)>1):
    pathlen = len(path)
    self.composeDict(gkey,result,pv,path,1, pathlen - 1)
    return result

    def dict2list(self,res={}):
    """
    之前是列表也按照字典来组装了,现在按照字符串将列表的地方改为列表
    :param result:
    :return:最终完整的json
    """
    def d2l(result={}):
    for key,value in result.items(): #result是第一层
    if(type(value)==dict):
    keys = value.keys() #value是第二层
    k0=list(keys)[0]
    if (type(k0) == int): #k0是第三层
    kv = []
    for k in keys:
    v = value.get(k)
    kv.append(v)
    if(type(v)==dict):
    d2l(v)
    result[key]=kv
    else:
    d2l(value)
    else:
    pass
    d2l(res)
    return res

    def update(self,data,path,newvalue):
    """
    Update JSON
    :param data:Target JSON
    :param path:Route as '/valuelist/(int)0/expiration'
    :param newvalue:Modified value
    :return:Updated JSON
    """
    newpaths=self.updateValue(data,path,newvalue)
    if(len(newpaths)==0):
    return {}
    else:
    comJSON = rc.composeJSON(newpaths)
    lastJson = rc.dict2list(comJSON)
    return lastJson

    def addkv(self,data,path,key=None,value=None):
    """
    for example addkv(dataA,'/data/customer','age',30)
    :param data: Target JSON
    :param path:Location of new field,as '/data/customer'
    :param key: new field
    :param value:new field value
    :return:Added JSON
    """
    resultStr=self.resolution(data)
    kv={}
    if(key!=None):
    kv['path']=path+'/'+key
    else:
    kv['path'] = path
    kv['value']=value
    resultStr.append(kv)
    newpaths=self.pathlist(resultStr)
    if (len(newpaths) == 0):
    return {}
    else:
    comJSON = rc.composeJSON(newpaths)
    lastJson = rc.dict2list(comJSON)
    return lastJson

    def delete(self,data,path):
    """
    Delete the node of the specified path
    :param data:Target JSON
    :param path:path
    :return:JSON after deleting a node
    """
    paths=self.resolution(data)
    templist=[]
    for pathv in paths:
    p=pathv.get('path')
    index=p.find(path)
    if(index==0):
    other=p[index+len(path):]
    if(len(other)>0):
    otherOne=other[0]
    if((path ==p) or (otherOne=='/')):
    pass
    else:
    templist.append(pathv)
    else:
    templist.append(pathv)
    newpaths =self.pathlist(templist)
    if (len(newpaths) == 0):
    return {}
    else:
    comJSON = rc.composeJSON(newpaths)
    lastJson = rc.dict2list(comJSON)
    return lastJson

    def getKeys(self,data):
    keysAll_list = []
    def getkeys(data): # Traverse all keys of JSON
    if (type(data) == type({})):
    keys = data.keys()
    for key in keys:
    value = data.get(key)
    if (type(value) != type({}) and type(value) != type([])):
    keysAll_list.append(key)
    elif (type(value) == type({})):
    keysAll_list.append(key)
    getkeys(value)
    elif (type(value) == type([])):
    keysAll_list.append(key)
    for para in value:
    if (type(para) == type({}) or type(para) == type([])):
    getkeys(para)
    else:
    keysAll_list.append(para)
    getkeys(data)
    return keysAll_list

    def isExtend(self, ddict={}, tagkey=None): # Check whether the target field tagkey is in data (JSON data)
    if (type(ddict) != type({})):
    pass
    else:
    datalen=len(ddict.keys())
    if(datalen==0):
    pass
    else:
    key_list = self.getKeys(ddict)
    for key in key_list:
    if (key == tagkey):
    return True
    return False
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
    182
    183
    184
    185
    186
    187
    188
    189
    190
    191
    192
    193
    194
    195
    196
    197
    198
    199
    200
    201
    202
    203
    204
    205
    206
    207
    208
    209
    210
    211
    212
    213
    214
    215
    216
    217
    218
    219
    220
    221
    222
    223
    224
    225
    226
    227
    228
    229
    230
    231
    232
    233
    234
    235
    236
    237
    238
    239
    240
    241
    242
    243
    244
    245
    246
    247
    248
    249
    250
    251
    252
    253
    254
    255
    256
    257
    258
    259
    260
    261
    262
    验证

    if __name__ == '__main__':
    rc=rcjson()
    dataA={"code": 0,
    "data": {"areaCode": "86", "avatar": "", "countryCode": "86", "customer_risk_type": "0","customer":{"name":"syc","sex":"m"}},
    "valuelist":[{"expiration": 1578043337756, "extendStatusBit": 1, "firstLogin": "True", "id": 11529},
    {"expiration": 1578043337757, "extendStatusBit": 2, "firstLogin": "True", "id": 11539,"transaction":[{"stockcode":"601235"},{"price":2.12}]},
    {"expiration": 1578043337758, "extendStatusBit": 3, "firstLogin": "True", "id": 11549},
    {"expiration": 1578043337759, "extendStatusBit": 4, "firstLogin": "True", "id": 11559}
    ],
    "msg": "成功"}
    #修改
    # result=rc.update(dataA,'/valuelist/(int)1/test01/(int)1/price',10.5)
    # print(result)
    #新增
    result=rc.addkv(dataA,'/data/customer/',key='age',value=30)
    print(result)
    #删除
    # result=rc.delete(dataA,'/valuelist/(int)1/test01/(int)0/stockcode')
    # print(result)

  • 相关阅读:
    爬取博客园有关爬虫的文章
    小只爬虫的相关思路
    fiddler显示出服务器IP方法
    在测试时用到的一些mysql的小技巧(持续更新)
    把python脚本打包成win可执行文件
    关于SQL中的ROWNUM问题
    关于C#的DataGridView设置了DataSource后Rows无值问题
    微信小程序wx.request的简单封装
    ASP.NET进行请求转发
    微信小程序设置滚动条
  • 原文地址:https://www.cnblogs.com/shuyichao/p/12407845.html
Copyright © 2020-2023  润新知