解决方案
object_hook
import jsondef json_load_byteified(file_handle): return _byteify( json.load(file_handle, object_hook=_byteify), ignore_dicts=True )def json_loads_byteified(json_text): return _byteify( json.loads(json_text, object_hook=_byteify), ignore_dicts=True )def _byteify(data, ignore_dicts = False): # if this is a unipre string, return its string representation if isinstance(data, unipre): return data.enpre('utf-8') # if this is a list of values, return list of byteified values if isinstance(data, list): return [ _byteify(item, ignore_dicts=True) for item in data ] # if this is a dictionary, return dictionary of byteified keys and values # but only if we haven't already byteified it if isinstance(data, dict) and not ignore_dicts: return { _byteify(key, ignore_dicts=True): _byteify(value, ignore_dicts=True) for key, value in data.iteritems() } # if it's anything else, return it in its original form return data用法示例:
>>> json_loads_byteified('{"Hello": "World"}'){'Hello': 'World'}>>> json_loads_byteified('"I am a top-level string"')'I am a top-level string'>>> json_loads_byteified('7')7>>> json_loads_byteified('["I am inside a list"]')['I am inside a list']>>> json_loads_byteified('[[[[[[[["I am inside a big nest of lists"]]]]]]]]')[[[[[[[['I am inside a big nest of lists']]]]]]]]>>> json_loads_byteified('{"foo": "bar", "things": [7, {"qux": "baz", "moo": {"cow": ["milk"]}}]}'){'things': [7, {'qux': 'baz', 'moo': {'cow': ['milk']}}], 'foo': 'bar'}>>> json_load_byteified(open('somefile.json')){'more json': 'from a file'}它是如何工作的,为什么要使用它?
Mark Amery的功能比这些功能更短,更清晰,那么它们的意义何在?你为什么要使用它们?
纯粹是为了表现。Mark的答案首先使用
unipre字符串完全解码JSON文本,然后遍历整个解码值以将所有字符串转换为字节字符串。这有一些不良影响:
- 整个解码结构的副本在内存中创建
- 如果你的JSON对象确实是深层嵌套(500个级别或更多),那么你将达到Python的最大递归深度
这个答案通过缓解这两方面的性能问题
object_hook的参数
json.load和
json.loads。从文档:
object_hook是一个可选函数,它将被解码的任何对象文字
(a dict)的结果调用。将使用
object_hook的返回值代替
dict。此功能可用于实现自定义解码器
由于嵌套在其他字典中许多层次的字典
object_hook在解码时会传递给它们,因此我们可以在那时将其中的任何字符串或列表字节化,并避免以后再进行深度递归。
Mark的答案不适合按
object_hook现状使用,因为它会递归为嵌套词典。我们阻止这个答案与该递归
ignore_dicts参数
_byteify,它被传递给它在任何时候都只是当
object_hook它传递一个新dict来
byteify。该
ignore_dicts标志指示
_byteify忽略
dicts,因为它们已经被字节化了。
最后,我们的实现
json_load_byteified和在从或返回的结果上
json_loads_byteified调用
_byteify(with ignore_dicts=True)来处理被解码的JSON文本在顶层没有的情况。
json.loadjson.loadsdict



