jsonの順序を保ったままOrderedDictを作る

jsonの順序を保ったままOrderedDictを作る方法はobject_pairs_hookにOrderedDictを指定してあげれば良い

import json
from collections import OrderedDict
from functools import partial

loads = partial(json.loads, object_pairs_hook)

data = '''
{
  "x": [1, 2, 3],
  "y": "foo",
  "z": {"a": "a", "b": "b"}
}
'''

print(loads(data))
# OrderedDict([('x', [1, 2, 3]), ('y', 'foo'), ('z', OrderedDict([('a', 'a'), ('b', 'b')]))])

ちなみにjson.loadsのコードを見ると以下の様に書かれている。

_default_decoder = JSONDecoder(object_hook=None, object_pairs_hook=None)

def loads(s, encoding=None, cls=None, object_hook=None, parse_float=None,
        parse_int=None, parse_constant=None, object_pairs_hook=None, **kw):
    if (cls is None and object_hook is None and
            parse_int is None and parse_float is None and
            parse_constant is None and object_pairs_hook is None and not kw):
        return _default_decoder.decode(s)
    if cls is None:
        cls = JSONDecoder
    if object_hook is not None:
        kw['object_hook'] = object_hook
    if object_pairs_hook is not None:
        kw['object_pairs_hook'] = object_pairs_hook
    if parse_float is not None:
        kw['parse_float'] = parse_float
    if parse_int is not None:
        kw['parse_int'] = parse_int
    if parse_constant is not None:
        kw['parse_constant'] = parse_constant
    return cls(**kw).decode(s)

なのでJSONDecoderのインスタンスを作った方がちょっとだけ速い。ただし微々たるもの。

gist7f283bf8294c235cc1ea