json - Find and modify python nested dictionary (key, value) -


i have json file need update. converting python dict (nested) update it. here input, dept. i'm sure there better way this, don't know.

ultimatley want able perfom create/delete action in addition update.


here script , input file.

# find target value in nested key value chain  # replace old value newvalue  import json pprint import pprint d1 = open('jinputstack.json', 'r') d1 = json.load(d1)  def traverse(obj, path=none, callback=none):     """     traverse python object structure, calling callback function every element in structure,     , inserting return value of callback new value.     """     if path none:         path = []      if isinstance(obj, dict):         value = {k: traverse(v, path + [k], callback)                  k, v in obj.items()}     elif isinstance(obj, list):         value = [traverse(elem, path + [[]], callback)                  elem in obj]     else:         value = obj      if callback none:         # print("starting value found-----------------------------------------------------")         print(value)         return value      else:         print(path, value)         return callback(path, value)   def traverse_modify(obj, target_path, action):     """     traverses arbitrary object structure , performs given action on value,      replacing node     action's return value.     """     target_path = to_path(target_path)     pprint(value)     pprint(target_path)      def transformer(path, value):         if path == target_path:             print(action)             d2 = data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"].update(action)             return d2          else:             return value      return traverse(obj, callback=transformer)   def to_path(path):     """     helper function, converting path strings path lists.         >>> to_path('foo')         ['foo']         >>> to_path('foo.bar')         ['foo', 'bar']         >>> to_path('foo.bar[]')         ['foo', 'bar', []]     """     if isinstance(path, list):         return path  # in list format      def _iter_path(path):          #pprint(path.split)          parts in path.split('[]'):             part in parts.strip('.').split('.'):                 yield part             yield []      return list(_iter_path(path))[:-1]  def updateit(newvalue):      data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"] = newvalue      print(data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"])     return data["groups"][0]["properties"][1]["value"]["data"][2]["object"]["name"]  traverse_modify(d1, d1["groups"][0]["properties"][1]["value"]["data"][1]["object"]["name"], updateit("xxxxxxxxxxxxxx"))  json_data = json.dumps(data)  f = open("jinputstack.json","w") f.write(json_data) f.close() 

jinputstack.json = {   "groups": [     {       "name": "group1",       "properties": [         {           "name": "test-key-string",           "value": {             "type": "string",             "encoding": "utf-8",             "data": "value1"           }         },         {           "name": "test-key-valuearray",           "value": {             "type": "valuearray",             "data": [               {                 "data": true               },               {                 "type": "blob",                 "object": {                   "name": "john su",                   "age": 25,                   "salary": 104000.45,                   "married": false,                   "gender": "male"                 }               }             ]           }         }       ],       "groups": [         {           "name": "group-child",           "properties": [             {               "name": "test-key-string"             },             {               "name": "test-key-list",               "value": {                 "type": "list",                 "data": [                   "string1",                   "string2",                   "string3"                 ]               }             }           ]         }       ]     },     {       "name": "group2",       "properties": [         {           "name": "test-key2-string",           "value": {             "type": "string",             "encoding": "utf-8",             "data": "value2"           }         },         {           "name": "microbox"         }       ]     }   ] } 

credit goes original author: vincent driessen

i think best way convert json object xml , use elementtree , xpath parse , modify object. later can revert json if need:

import json xmljson import parker lxml.etree import element  dataxml = parker.etree(datajson, root=element('root')) print(dataxml.find('.//data//name').text)            # john su dataxml.find('.//data//name').text = "joan d'arc" print(dataxml.find('.//data//name').text)            # joan d'arc print(json.dumps(parker.data(dataxml))) 

there packages xpath on json string directly. 1 of them, jsonpath-rw changes syntax. prefer stick standard xpath syntax.

from jsonpath_rw import jsonpath, parse  expr = parse('$..data..name')   # notice . $ , / .                                 # confusing enough? expr.find(datajson)[0] = 'yyyy' print(expr.find(datajson)[0].value)                  # john su 

another 1 xjpath simple , perhaps easier learn, not give difference doing now.

import xjpath  xj = xjpath.xjpath(datajson) print(xj['groups.@0.properties.@1.value.data.@1.object.name'])  # not different code: print(data["groups"][0]["properties"][1]["value"]["data"][1]["object"]["name"]) 

i hope helps.


Comments

Popular posts from this blog

jOOQ update returning clause with Oracle -

java - Warning equals/hashCode on @Data annotation lombok with inheritance -

java - BasicPathUsageException: Cannot join to attribute of basic type -