Can I get JSON to load into an OrderedDict?

前端 未结 6 936
别跟我提以往
别跟我提以往 2020-11-22 01:13

Ok so I can use an OrderedDict in json.dump. That is, an OrderedDict can be used as an input to JSON.

But can it be used as an output? If so how? In my

相关标签:
6条回答
  • 2020-11-22 01:50

    Simple version for Python 2.7+

    my_ordered_dict = json.loads(json_str, object_pairs_hook=collections.OrderedDict)
    

    Or for Python 2.4 to 2.6

    import simplejson as json
    import ordereddict
    
    my_ordered_dict = json.loads(json_str, object_pairs_hook=ordereddict.OrderedDict)
    
    0 讨论(0)
  • 2020-11-22 01:50

    You could always write out the list of keys in addition to dumping the dict, and then reconstruct the OrderedDict by iterating through the list?

    0 讨论(0)
  • 2020-11-22 01:53

    Some great news! Since version 3.6 the cPython implementation has preserved the insertion order of dictionaries (https://mail.python.org/pipermail/python-dev/2016-September/146327.html). This means that the json library is now order preserving by default. Observe the difference in behaviour between python 3.5 and 3.6. The code:

    import json
    data = json.loads('{"foo":1, "bar":2, "fiddle":{"bar":2, "foo":1}}')
    print(json.dumps(data, indent=4))
    

    In py3.5 the resulting order is undefined:

    {
        "fiddle": {
            "bar": 2,
            "foo": 1
        },
        "bar": 2,
        "foo": 1
    }
    

    In the cPython implementation of python 3.6:

    {
        "foo": 1,
        "bar": 2,
        "fiddle": {
            "bar": 2,
            "foo": 1
        }
    }
    

    The really great news is that this has become a language specification as of python 3.7 (as opposed to an implementation detail of cPython 3.6+): https://mail.python.org/pipermail/python-dev/2017-December/151283.html

    So the answer to your question now becomes: upgrade to python 3.6! :)

    0 讨论(0)
  • 2020-11-22 01:55

    The normally used load command will work if you specify the object_pairs_hook parameter:

    import json
    from  collections import OrderedDict
    with open('foo.json', 'r') as fp:
        metrics_types = json.load(fp, object_pairs_hook=OrderedDict)
    
    0 讨论(0)
  • 2020-11-22 01:56

    In addition to dumping the ordered list of keys alongside the dictionary, another low-tech solution, which has the advantage of being explicit, is to dump the (ordered) list of key-value pairs ordered_dict.items(); loading is a simple OrderedDict(<list of key-value pairs>). This handles an ordered dictionary despite the fact that JSON does not have this concept (JSON dictionaries have no order).

    It is indeed nice to take advantage of the fact that json dumps the OrderedDict in the correct order. However, it is in general unnecessarily heavy and not necessarily meaningful to have to read all JSON dictionaries as an OrderedDict (through the object_pairs_hook argument), so an explicit conversion of only the dictionaries that must be ordered makes sense too.

    0 讨论(0)
  • 2020-11-22 02:04

    Yes, you can. By specifying the object_pairs_hook argument to JSONDecoder. In fact, this is the exact example given in the documentation.

    >>> json.JSONDecoder(object_pairs_hook=collections.OrderedDict).decode('{"foo":1, "bar": 2}')
    OrderedDict([('foo', 1), ('bar', 2)])
    >>> 
    

    You can pass this parameter to json.loads (if you don't need a Decoder instance for other purposes) like so:

    >>> import json
    >>> from collections import OrderedDict
    >>> data = json.loads('{"foo":1, "bar": 2}', object_pairs_hook=OrderedDict)
    >>> print json.dumps(data, indent=4)
    {
        "foo": 1,
        "bar": 2
    }
    >>> 
    

    Using json.load is done in the same way:

    >>> data = json.load(open('config.json'), object_pairs_hook=OrderedDict)
    
    0 讨论(0)
提交回复
热议问题