如何将dict转换为递归defaultdict并加载JSON?

时间:2018-06-06 22:06:16

标签: python json python-2.7 recursion defaultdict

是否可以使用Python 2.7将JSON代码加载到递归defaultdict以避免KeyError

例如:

from __future__ import print_function
from collections import defaultdict
import json

S =  '{"a": [{"b": "TEST1", "p": "TEST2"}, {"b": "TEST3", "p": "TEST4"}]}'

d = json.loads(S)
nd = lambda: defaultdict(nd)
ni = nd()
print('1: ', ni['a'][0]['b'])
ni.update(d)
print('2: ', ni['a'][0]['b'])
print('3: ', ni['a'][1]['p'])
print('4: ', ni['a'][1]['c'])

结果

1:  defaultdict(<function <lambda> at 0x0266F530>, {})
2:  TEST1
3:  TEST4
Traceback (most recent call last):
  File "C:/...", line 16, in <module>
    print('4: ', ni['a'][1]['c'])
KeyError: 'c'

ni.update(d) ni作为dict后工作,而不像递归defaultdict。有没有办法将dict添加到递归defaultdict并保留其属性?

我希望第4步的结果类似于以下内容:

4:  defaultdict(<function <lambda> at 0x0266F530>, {})

1 个答案:

答案 0 :(得分:2)

创建递归字典还不够。您必须递归地将JSON对象加载到dict中。

您的代码中发生的事情是ni['a']是普通字典,而不是nd类型的字典。当您运行ni.update(d)时,更新并不足以遍历d,将每个级别的对象写入相似类型的对象。相反,它只是将d的第一级值和键复制到ni。第一级值只是普通的dicts或其他。

要正确初始化ni,您需要编写一个递归函数来确定每个值是否为dict,数组或标量。如果它是一个字典,则必须调用nd,然后用相同递归方式处理的值填充结果。

或者,您可以将参数object_hook用于json.loads。有关详细信息,请参阅https://docs.python.org/2/library/json.html#json.load。无论你在这里传递什么函数,都会在任何解析级别创建的每个dict上调用。所以功能

def defaultdict_from_dict(d):
    nd = lambda: defaultdict(nd)
    ni = nd()
    ni.update(d)
    return ni

或者类似的东西可能会对你有所帮助。