如何在Python的json文件中将键与嵌套级别连接起来?

时间:2017-03-03 21:50:19

标签: python json dictionary web-scraping

我正在解决一个问题,我有一个json对象文件,如下所示:

{
    "id": "111",
    "name": {
        "firstname": "Tamara",
        "lastname": "Myers"
    },
    "address": {
        "street": "20722 Coleman Villages,East Rose",
        "zip": "71064-5894"
    }
}

我想将其转换为:

{
    "id": "111",
    "name_firstname": "Tamara",
    "name_lastname": "Myers",
    "address_street": "20722 Coleman Villages,East Rose",
    "address_zip": "71064-5894"
}

我无法做到这一点,因为我们可能在其他json对象中有更多字段,这些字段在上面的例子中没有给出。

例如"Job":{"Engineer":"Junior","domain":"civil"}。并且所有json对象中的嵌套级别也是不规则的。

5 个答案:

答案 0 :(得分:2)

您需要一个递归函数:与whilefor循环不同,它不关心嵌套级别。

(递归函数只是一个调用自身的函数)

想法是

  • 创建一个新对象(目标对象)
  • 在递归函数中
    • 循环遍历原始对象的每个键
      • 如果值是dict,请再次调用函数
      • 否则,将格式化的密钥(带下划线)和值添加到目标对象
def flat_keys(obj, new_obj={}, keys=[]):
    for key, value in obj.items():
        if isinstance(value, dict):
            # call the function again if the value is a dict
            # we go one step deeper: obj[key]
            # give the new_obj (by reference, so each call edit the *same* object)
            # give to used keys: keys + [key]
            flat_keys(obj[key], new_obj, keys + [key])
        else:
            new_obj['_'.join(keys + [key])] = value
    return new_obj

new_obj = flat_keys(json.JSONDecoder().decode("your object"))
print(new_obj)

答案 1 :(得分:2)

你需要一个递归函数。但是这个比其他提供的更简单。它还将基础案例放在首位,这将有助于堆栈大小。我不能让它拖尾递归。

def merge_keys(d):
  to_return = {}
  for key, value in d.items():
    if not isinstance(value, dict):
      to_return[key] = value
    else:
      for merged_key, merged_value in merge_keys(value).items():
        to_return["_".join((key, merged_key))] = merged_value
  return to_return

答案 2 :(得分:1)

我相信递归生成器会很好:

def nested_to_flat(data):                     
     for k, v in data.items():
         if isinstance(v, dict):
             for x, y in nested_to_flat(v):
                 yield ('%s_%s' % (k, x), y)
             continue
         yield (k, v)

并使用如下:

result = {k: v for k, v in nested_to_flat(data)}

答案 3 :(得分:1)

import sys
sys.path.insert(0, '.')
from sys import stderr


def pare(data, key, is_verbose=False):

   parts = key.split('.')

   i = 0
   ptr = data

   for part in parts:
       if is_verbose is True:
          if i > 0:
              stderr.write(' -> ')

          stderr.write(part)

       try:
          if issubclass(ptr.__class__, list) is True:
              ptr = ptr[int(part)]
          else:
              ptr = ptr[part]
       except:
          if is_verbose is True:
              stderr.write("\n")
          raise ValueError("Could not descend to child node: %s" % (part))
       i += 1
    if is_verbose is True:
       stderr.write("\n")
    return ptr
def path_list(dictionary, path):

    key_path_list = []
    if dictionary.__class__.__name__ == 'dict':
        if len(dictionary.keys())>0:
          i = 0
          n = len(dictionary.keys())
          while i< n:
              new_path  = dictionary.keys()[i]
              i += 1
              key_path = path + '.' + new_path
              key_path_list.append(key_path)
    else:
        pass
return key_path_list

def rec_data(data, key_path):
    pared = pare(data, key_path)
    value = []
    nd = {}
    if pared.__class__.__name__ == 'dict':
        paths = path_list(pared, key_path)
        for p in paths:
           if p in paths:
                   sl = pare(data, p)
                   nd[p] =sl
                   value.append(sl)
           else:
              pass
           rec_data(data, p)
    else:
        nd[key_path] = pared
    return nd
def main():
    json = {
    "id": "111",
    "name": {
       "firstname": "Tamara",
       "lastname": "Myers"
    },
    "address": {
       "street": "20722 Coleman Villages,East Rose",
       "zip": "71064-5894"
     }
     }

    dic = {}
    for k,v in json.items():
        dic.update(rec_data(json,k))
    print dic
if __name__ == "__main__":

    main()

答案 4 :(得分:0)

在Python中,您可以在fly

创建密钥
dic = {}
dic["key"] = value
dic["key"] = "value"
print dic
{'key': 'value'}

你可以用你的对象做这样的事情:

myNewDic = {}
for key, value in dic.items():
    if isinstance(value,dict):
        for k, v in value.items():
            myNewDic[key+"_"+k] = v
    else:
       myNewDic[key] = value

检查是否有效,我想我正在路上。

快乐编码