2 回答

TA贡献1777条经验 获得超10个赞
您可以用JSONDecoder.object_pairs_hook来自定义JSONDecoder解码对象的方式。这个钩子函数将被传递一个(key, value)您通常会对其进行一些处理的成对列表,然后变成一个dict。
但是,由于Python字典不允许重复的键(而且您根本无法更改键),因此在(key, value)解码JSON时,您可以在挂钩中保持不变地返回对,并获得嵌套的对列表:
from json import JSONDecoder
def parse_object_pairs(pairs):
return pairs
data = """
{"foo": {"baz": 42}, "foo": 7}
"""
decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)
obj = decoder.decode(data)
print obj
输出:
[(u'foo', [(u'baz', 42)]), (u'foo', 7)]
您如何使用此数据结构取决于您。如上所述,Python字典不允许重复的键,而且没有办法解决。您甚至将如何基于密钥进行查找?dct[key]会模棱两可。
因此,您既可以实现自己的逻辑来以期望的方式处理查找,也可以实现某种避免碰撞的功能,以使键(如果不是)变得唯一,然后从嵌套列表中创建字典。
编辑:既然您说过要修改重复键以使其唯一,请按以下步骤进行操作:
from collections import OrderedDict
from json import JSONDecoder
def make_unique(key, dct):
counter = 0
unique_key = key
while unique_key in dct:
counter += 1
unique_key = '{}_{}'.format(key, counter)
return unique_key
def parse_object_pairs(pairs):
dct = OrderedDict()
for key, value in pairs:
if key in dct:
key = make_unique(key, dct)
dct[key] = value
return dct
data = """
{"foo": {"baz": 42, "baz": 77}, "foo": 7, "foo": 23}
"""
decoder = JSONDecoder(object_pairs_hook=parse_object_pairs)
obj = decoder.decode(data)
print obj
输出:
OrderedDict([(u'foo', OrderedDict([(u'baz', 42), ('baz_1', 77)])), ('foo_1', 7), ('foo_2', 23)])
该make_unique函数负责返回无冲突键。在这个例子中,它只是后缀与关键_n地方n是一个递增计数器-只是它适应您的需求。
由于object_pairs_hook完全按照JSON文档中出现的顺序接收对,因此也可以使用来保留该顺序OrderedDict,我也将其包括在内。

TA贡献1824条经验 获得超5个赞
非常感谢@Lukas Graf,我通过实现自己的钩子函数版本也使它正常工作
def dict_raise_on_duplicates(ordered_pairs):
count=0
d=collections.OrderedDict()
for k,v in ordered_pairs:
if k in d:
d[k+'_dupl_'+str(count)]=v
count+=1
else:
d[k]=v
return d
剩下的唯一事情就是自动摆脱双括号,我完成了:D再次感谢
添加回答
举报