如何在任意嵌套的深度处理字典属性?

时间:2016-02-19 21:26:32

标签: python json dictionary

我正在解析json - >具有嵌套在任意深度的值的dict对象。例如,外层是字段(数据来自客户服务票务系统),例如'name','sprint_team'等......但是对于某些字段,它们有一个嵌套的dict有'id','value'等值......

我将它全部放在一个平面文件中然后复制到AWS Redshift,但我正在试图找出一种有效的方法来处理我可能需要的所有不同嵌套级别的值。我正在考虑使用查找表,例如:

lookup = {
'customfield_12700': ('sprint_team', 'name'),
'customfield_13208': ('department', 'sub_department', 'name') 
}

其中value[0]始终是查找名称,然后可以有n个额外参数,这将是我的嵌套级别。我首先使用查找表的原因是因为Jira使用自定义域,我需要将它们映射到我们的云数据库中的列名。例如,在sprint_team字段中,我需要{flat}文件的name属性等等。

我怎样才能创建一个能够获取字典对象的函数,然后使用查找表返回我需要的值,无论它嵌套的深度如何?

1 个答案:

答案 0 :(得分:2)

这样的东西?

这使用了您的查找表构思,并且一次只能向下导航一个级别。

>>> data = {"foo": {"bar": {"baz": 1}}}
>>> lookup = {
...   'customfield': ("foo", "bar", "baz" )
... }

>>> def nest(data, name):
...   path = lookup[name]
...   d = data
...   for p in path:
...     d = d[p]
...   return d
...
>>> nest(data, 'customfield')
1

这也可以递归完成,除非你的非常深深嵌套,否则这应该没问题!

def nest(data, path):
      if len(path) == 0:
          return data
      else:
          return nest(data[path[0]], path[1:])

def find(data, name):
    return nest(data, lookup[name])

>>>find(data, 'customfield')
1

或者,使用时髦的功能方法:

>>> from operator import itemgetter
>>> from functools import reduce
>>> def compose(*functions):
...     return reduce(lambda f, g: lambda x: f(g(x)), functions, lambda x: x)

>>> nest = compose(*[itemgetter(name) for name in reversed(lookup['customfield'])])
>>> nest(data)
1

itemgetter提供了一个访问具有指定名称的属性的函数。 compose将这些函数组合在一起,以创建一个提取嵌套数据的函数。

您也可以预先生成这些函数并将它们存储在lookup而不是路径中,以便在需要时直接使用它们。

(我们必须定义自己的compose函数,因为Python没有内置函数。