【问题标题】:Preserving order AND maintaining all keys when loading JSON?加载 JSON 时保留顺序并维护所有密钥?
【发布时间】:2017-03-13 03:11:33
【问题描述】:

使用here 描述的方法,我在加载嵌套 JSON 文件时将OrderedDict 传递为object_pairs_hook,以保持顺序。

订单被保留,这对于 大多数 JSON 对象来说很好。但是 JSON 的某些部分(在嵌套的最低级别)如下所示:

"In Content" : { "Sulvo" : "abc.com_336x280_he-inlinecontentmobile", "Sulvo" : "abc.com_336x280_he-inlinecontentmobile_level2", "Sulvo" : "abc.com_336x280_he-inlinecontentmobile_level3", "Adsense" : "" },

在处理时,只会保留这些相同的密钥之一:

OrderedDict([(u'Sulvo', u'homeepiphany.com_336x280_he-inlinecontentmobile_level3'), (u'Adsense', u'')])),

我知道我们可以有一个字典,其中包含多个具有相同键名的项目,defaultdict。但是以下方法不起作用,即使它起作用了,我认为我们会获得钥匙但失去订单,所以我们也不会更好:

j = json.load(open('he.json'), object_pairs_hook=defaultdict)

是否可以保持顺序AND一次性保存所有密钥?

Python 2.7.12

【问题讨论】:

    标签: python python-2.7 dictionary ordereddictionary defaultdict


    【解决方案1】:

    如果您查看docs for json.load,它们会概述object_pairs_hook 参数的作用:

    object_pairs_hook 是一个可选函数,将使用任何对象字面量的结果来调用,该对象字面量使用有序的对列表进行解码。将使用object_pairs_hook 的返回值代替dict

    您需要做的就是编写一个函数,给定(key, value) 对的列表,构造您的对象。

    一种方法是什么都不做,直接传递项目列表而不构建字典:

    def handle_mapping(items):
        return items
    

    然后,您的 JSON 被解析如下:

    [(u'In Content',
      [(u'Sulvo', u'abc.com_336x280_he-inlinecontentmobile'),
       (u'Sulvo', u'abc.com_336x280_he-inlinecontentmobile_level2'),
       (u'Sulvo', u'abc.com_336x280_he-inlinecontentmobile_level3'),
       (u'Adsense', u'')])]
    

    如果你确实想将重复键的值合并到一个列表中,你可以使用OrderedDict

    def handle_mapping(items):
        d = OrderedDict()
        duplicate_keys = set()
    
        for key, value in items:
            # So [('k', 'v')] becomes {'k': 'v'}
            if key not in d:
                d[key] = value
            else:
                # So [('k', 'v1'), ('k', 'v2')] becomes {'k': ['v1', 'v2']}
                if key not in duplicate_keys:
                    duplicate_keys.add(key)
                    d[key] = [d[key]]
    
                d[key].append(value)
    
        return d
    

    然后,您的对象将被解析为:

    OrderedDict([(u'In Content',
                  OrderedDict([(u'Sulvo',
                                [u'abc.com_336x280_he-inlinecontentmobile',
                                 u'abc.com_336x280_he-inlinecontentmobile_level2',
                                 u'abc.com_336x280_he-inlinecontentmobile_level3']),
                               (u'Adsense', u'')]))])
    

    【讨论】:

    • 这是一个非常棒的答案。我得到了handle_mapping() 的建议。令我惊讶的是,仅将 json 文件传递​​给 json.load() - 即未指定 object_pairs_hook - 也会导致项目丢失,而传递虚拟函数会导致它们被保留。明天将尝试您的完整解决方案。谢谢。
    • @Pyderman:在 Python 中,dict([('a', 1), ('a', 1)]) == {'a': 1} == {'a': 1, 'a': 1},因为在字典中有重复的键没有意义(d['a'] 会做什么?)。 JavaScript(JSON 中的 J)做同样的事情。如果你的 JSON 和你的一样奇怪,你必须告诉 Python 使用字典以外的东西来保存你的元素。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-24
    • 2014-02-01
    • 2013-01-25
    • 2016-03-04
    • 2011-02-01
    • 2018-01-08
    • 1970-01-01
    相关资源
    最近更新 更多