2013-07-11 95 views
4

我有以下的JSON對象 -複雜的Python JSON對象的自定義詞典轉換

{ 
    "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" 
        } 
       } 
      ] 
     } 
    ] 
} 

我要尋找一些JSON遍歷到達所有的按鍵和轉換以上下列預期Python字典 -

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" 
         } 
       } 
     } 
    } 

需要遞歸函數來獲取資源& PerfList &數據和自定義字典。

可能有可能錯別字/ syntax_errs手熟預計字典...

這是我到目前爲止的代碼 - 但是,這是失敗的N個嵌套的資源。

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): 
     for 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): 
     for key in dict: 
      if key == self.KEY_RESULTS: 
       val = dict[key] 
       results = self.fetch_results(val) 

    def fetch_results(self,dict): 
     for 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): 
      for 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): 
      for 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): 
      for 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 
+3

你到目前爲止試過了什麼?你有沒有編寫任何代碼?如果你展示你的嘗試,那麼我們可以更好地指出你正確的方向。 – DMH

+0

@DMH我已經添加了我的一段代碼。但是,它不適用於多個嵌套資源和PerfLists。 –

回答

1

有時,當使用遞歸函數對嵌套結構進行操作時,它更容易考慮步行功能和操作函數。所以我們要定位json結構中包含的所有字典並對它們執行轉換操作。

在處理嵌套時,就地轉換結構而不是重新創建新結構要容易得多。從json結構構建嵌套字典的難度越大,涉及到能夠處理特定的json元素,將它們置於正確的深度和新結構的分支;這涉及兩個平行的步行操作。

但有一點需要注意,修改嵌套結構的同時走過它,因爲轉換操作可能會更改當前正在迭代行走功能的列表。在這種情況下,只有孩子(不是兄弟姐妹)在下部分支行走之前先進行修改。

from copy import deepcopy 
import json 
from pprint import pprint 
from 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 a nested list and dict structure, running func on all 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 
      for 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 
      for 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 and hasattr(func, "__call__")): 
     return walk_fun_lim_helper(ilist, func) 
    else: 
     return [] 

def transformers_robots_in_disguise(x): 
    for idict in x: 
     plist = idict.pop("PerfList", []) 
     plist = plist if(isinstance(plist, list)) else [plist] 
     for 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 = {} 
      for 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] 
     for 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) 
+1

這是一個夢幻般的工作..這只是無懈可擊的... 感謝您教育我的遞歸.. –

相關問題