Python json解析器允许重复键
我需要解析一个json文件,不幸的是,该文件不遵循原型。我的数据有两个问题,但是我已经找到了解决方法,所以我只在最后提一下,也许有人也可以提供帮助。
所以我需要解析这样的条目:
"Test":{
"entry":{
"Type":"Something"
},
"entry":{
"Type":"Something_Else"
}
}, ...
json默认解析器更新字典,因此仅使用最后一个条目。我不得不以某种方式存储另一个,我也不知道如何做到这一点。我还必须将密钥以它们在文件中出现的顺序存储在几个字典中,这就是为什么我使用OrderedDict这样做的原因。它工作正常,所以如果有任何办法可以用重复的条目来扩展它,我将不胜感激。
我的第二个问题是,这个非常相同的json文件包含如下条目:
"Test":{
{
"Type":"Something"
}
}
当Json.load()函数到达json文件中的该行时,将引发异常。解决此问题的唯一方法是自己手动卸下内支架。
提前致谢
-
您可以用
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
,我也将其包括在内。