您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python json解析器允许重复键

Python 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,我也将其包括在内。

python 2022/1/1 18:26:45 有226人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶