i have following json object -
{ "resource": [ { "@name": "bravo", "@signature": "h#bravo", "@type": "esx_5.x", "@typedisplayname": "esx server", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": [ { "@data": "26.00", "@end": "01:05:00", "@interval": "60", "@start": "01:04:00" }, { "@data": "24.00", "@end": "01:04:00", "@interval": "60", "@start": "01:03:00" }, { "@data": "36.00", "@end": "01:03:00", "@interval": "60", "@start": "01:02:00" }, { "@data": "38.00", "@end": "01:02:00", "@interval": "60", "@start": "01:01:00" }, { "@data": "37.00", "@end": "01:01:00", "@interval": "60", "@start": "01:00:00" } ] }, "resource": [ { "@name": "tango", "@signature": "vm#tango", "@type": "vm", "@typedisplayname": "virtual machine", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": { "@data": "12.00", "@end": "04:05:00", "@interval": "60", "@start": "04:04:00" } } }, { "@name": "charlie", "@signature": "vm#charlie", "@type": "vm", "@typedisplayname": "virtual machine", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": [ { "@data": "12.00", "@end": "04:20:00", "@interval": "60", "@start": "04:19:00" }, { "@data": "12.00", "@end": "04:19:00", "@interval": "60", "@start": "04:18:00" } ] } } ] }, { "@name": "alpha", "@signature": "h#alpha", "@type": "esx_5.x", "@typedisplayname": "esx server", "perflist": [ { "@attrid": "cpuusage", "@attrname": "usage", "data": { "@data": "9", "@end": "06:10:00", "@interval": "60", "@start": "06:09:00" } }, { "@attrid": "cpuusagemhz", "@attrname": "usage mhz", "data": { "@data": "479", "@end": "06:10:00", "@interval": "60", "@start": "06:09:00" } } ] } ] }
i looking json traversal reach keys , convert above following expected python dictionary -
d = { 'esx_5.x' : { 'bravo' : { "@typedisplayname" : "esx server", "@signature" : "h#bravo", "cpuusage" : { "from_01:04:00_to_01:05:00" : 26.00, "from_01:03:00_to_01:04:00" : 24.00, "from_01:02:00_to_01:03:00" : 36.00, "from_01:01:00_to_01:02:00" : 38.00, "from_01:00:00_to_01:01:00" : 37.00, "interval" : 60 }, "vm" : { "tango" : { "@typedisplayname" : "virtual machine", "@signature" : "vm#tango", "cpuusage" : { "from_04:04:00_to_04:05:00" : 12.00, "interval" : 60 } }, "charlie" : { "@typedisplayname" : "virtual machine", "@signature": "vm#charlie", "cpuusage" : { "from_04:19:00_to_04:20:00" : "12.00", "from_04:18:00_to_04:19:00" : "12.00", "@interval": "60", } } }, }, 'alpha' : { "@typedisplayname" : "esx server", "@signature" : "h#alpha", "cpuusage" : { "from_06:09:00_to_06:10:00" : 9, "@interval": "60" }, "cpuusagemhz" : { "from_06:09:00_to_06:10:00" : 479, "@interval": "60" } } } }
need recursive functions fetch resources & perflist & data , customize dictionary.
there possible typos/syntax_errs in hand cooked expected dictionary...
here code far -- failing n number of nested resources.
import json class mqlprettyprint(): key_response = 'response' key_results = 'results' key_resource = 'resource' def __init__(self,file=none): self._json_file = file self._json_data = self.read_json_file() self._json_dict = self.json_to_dict() def json_file(self): return self._json_file def read_json_file(self): json_data = "" try: json = open(self._json_file,"r") json_data = json.read() json.close() except: raise return json_data def json_to_dict(self): return json.loads(self._json_data) def json_data(self): return self._json_data def json_dict(self): return self._json_dict def json2mql(self): key in self._json_dict: if key == self.key_response: val = self._json_dict[key] response = self.fetch_response(val) def fetch_response(self,dict): key in dict: if key == self.key_results: val = dict[key] results = self.fetch_results(val) def fetch_results(self,dict): key in dict: if key == self.key_resource: val = dict[key] resource = self.fetch_resource(val) def fetch_resource(self,resources,dict={}): if isinstance(resources,list): resource in resources: print "\n\n",resource if isinstance(resource,__builtins__.dict): #header = self.fetch_resource_header(resource) #perflist = self.fetch_perf_list(resource) self.fetch_resource(resource) elif isinstance(resources,dict): header = self.fetch_resource_header(resource) perflist = self.fetch_perf_list(resource) else: print resources def fetch_resouce_header(resource): name = resource['@name'] signature = resource['@signature'] type = resource['@type'] typedisplayname = resource['@typedisplayname'] resource_dict = {'@name' : name, '@signature' : signature, '@type' : type, '@typedisplayname' : typedisplayname} return resource_dict def fetch_perf_list(self,resource,perfdict={}): perflists = resource['perflist'] if isinstance(perflists,list): perf in perflists: self.fetch_perf_list(perf,perfdict) elif isinstance(perflists,dict): header = self.fetch_perf_header(perf) datalist = self.fetch_data(perf) key = "" if len(perfdict) == 0: key = header['@attrid'] perfdict[key] = header perfdict[key]['data'] = datalist else: if not perfdict.has_key(key): perfdict[key] = header perfdict[key]['data'] = datalist else: if perfdict.has_key('data'): perfdict[key]['data'].update(datalist) else: perfdict[key]['data'] = datalist else: print perflists return perfdict def fetch_perf_header(self,perfdict): header = {} attrid = perfdict['@attrid'] attrname = perfdict['@attrname'] header = {'@attrid' : attrid, '@attrname' : attrname} return header def fetch_data(self,perfdict,datadict={}): datalist = perfdict['data'] if isinstance(datalist,list): data in datalist: #fetch internal data self.fetch_data(data,datadict) elif isinstance(datalist,dict): start = datalist['@start'] end = datalist['@end'] interval = datalist['@interval'] data = datalist['@data'] key = "%s_%s" % (start,end) datadict[key] = datalist #data_dict = {key : datalist} #if len(datadict) == 0: # datadict[key] = data_dict #else: # datadict['data'].update(data_dict) else: print datalist return datadict
sometimes when operating on nested structures using recursive functions, easier think in terms of walking function , operation function. want target dicts contained in json structure , perform transformation operation on them.
transforming structure in-place, instead of recreating new one, easier when dealing nests. more difficult approach of constructing nested dicts json structure involves being able address specific json elements, place them @ correct depth , branch of new structure; involves 2 parallel walking operations.
one thing mindful of though, modifying nested structure while walking across transformation operation may change list walking function iterating on. in instance, children (not siblings) modified first before walking on lower branches.
from copy import deepcopy import json pprint import pprint stringio import stringio json_str = \ ''' { "resource": [ { "@name": "bravo", "@signature": "h#bravo", "@type": "esx_5.x", "@typedisplayname": "esx server", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": [ { "@data": "26.00", "@end": "01:05:00", "@interval": "60", "@start": "01:04:00" }, { "@data": "24.00", "@end": "01:04:00", "@interval": "60", "@start": "01:03:00" }, { "@data": "36.00", "@end": "01:03:00", "@interval": "60", "@start": "01:02:00" }, { "@data": "38.00", "@end": "01:02:00", "@interval": "60", "@start": "01:01:00" }, { "@data": "37.00", "@end": "01:01:00", "@interval": "60", "@start": "01:00:00" } ] }, "resource": [ { "@name": "tango", "@signature": "vm#tango", "@type": "vm", "@typedisplayname": "virtual machine", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": { "@data": "12.00", "@end": "04:05:00", "@interval": "60", "@start": "04:04:00" } } }, { "@name": "charlie", "@signature": "vm#charlie", "@type": "vm", "@typedisplayname": "virtual machine", "perflist": { "@attrid": "cpuusage", "@attrname": "usage", "data": [ { "@data": "12.00", "@end": "04:20:00", "@interval": "60", "@start": "04:19:00" }, { "@data": "12.00", "@end": "04:19:00", "@interval": "60", "@start": "04:18:00" } ] } } ] }, { "@name": "alpha", "@signature": "h#alpha", "@type": "esx_5.x", "@typedisplayname": "esx server", "perflist": [ { "@attrid": "cpuusage", "@attrname": "usage", "data": { "@data": "9", "@end": "06:10:00", "@interval": "60", "@start": "06:09:00" } }, { "@attrid": "cpuusagemhz", "@attrname": "usage mhz", "data": { "@data": "479", "@end": "06:10:00", "@interval": "60", "@start": "06:09:00" } } ] } ] } ''' def walk_fun_lim(ilist, func=none): ''' recursively walk nested list , dict structure, running func on dicts ''' def walk_fun_lim_helper(ilist, func=none, count=0): tlist = [] ttlist = [] if(isinstance(ilist, list)): ttlist = filter(lambda x: x, func(filter(lambda x: isinstance(x, dict), ilist))) if(ttlist): tlist += ttlist q in ilist: ttlist = filter(lambda x: x, walk_fun_lim_helper(q, func, count+1)) if(ttlist): tlist += ttlist elif(isinstance(ilist, dict)): ttlist = filter(lambda x: x, func([ilist])) if(ttlist): tlist += ttlist q in ilist: ttlist = filter(lambda x: x, walk_fun_lim_helper(ilist[q], func, count+1)) if(ttlist): tlist += ttlist return [tlist] if(count != 0) else tlist if(func != none , hasattr(func, "__call__")): return walk_fun_lim_helper(ilist, func) else: return [] def transformers_robots_in_disguise(x): idict in x: plist = idict.pop("perflist", []) plist = plist if(isinstance(plist, list)) else [plist] sub_dict in plist: sub_name = sub_dict.pop("@attrid") dlist = sub_dict.pop("data", []) dlist = dlist if(isinstance(dlist, list)) else [dlist] new_dict = {} sub_dict in dlist: new_dict["from_%(@start)s_to_%(@end)s" % sub_dict] = sub_dict["@data"] new_dict["@interval"] = sub_dict["@interval"] idict[sub_name] = new_dict rlist = idict.pop("resource", []) rlist = rlist if(isinstance(rlist, list)) else [rlist] sub_dict in rlist: sub_type = sub_dict.pop("@type") sub_name = sub_dict.pop("@name") idict.setdefault(sub_type, {})[sub_name] = sub_dict return [] json_data = json.load(stringio(json_str)) data_copy = deepcopy(json_data) walk_fun_lim(data_copy, transformers_robots_in_disguise) pprint(data_copy)
Comments
Post a Comment