更新 12/30/2014
实现这一目标的最简单方法是使用object_hook
的回调JSONDecoder
正如我下面的旧答案中所述。但是,由于这需要对数据中的每个键值对进行额外的函数调用,因此这可能会对性能产生影响。
所以,如果你真的想改变方式json
处理 None,你需要更深入地挖掘。这JSONDecoder
使用扫描器在 JSON 输入中查找某些标记。不幸的是,这是一个函数而不是一个类,因此子类化并不那么容易。扫描仪函数称为py_make_scanner
并可以在以下位置找到:json/扫描仪.py。它基本上是一个获取 JSONDecoder 作为参数并返回scan_once
功能。这scan_once
函数接收一个字符串和当前扫描仪位置的索引。
一个简单的定制扫描仪功能可能如下所示:
import json
def make_my_scanner(context):
# reference to actual scanner
interal_scanner = json.scanner.py_make_scanner(context)
# some references for the _scan_once function below
parse_object = context.parse_object
parse_array = context.parse_array
parse_string = context.parse_string
encoding = context.encoding
strict = context.strict
object_hook = context.object_hook
object_pairs_hook = context.object_pairs_hook
# customized _scan_once
def _scan_once(string, idx):
try:
nextchar = string[idx]
except IndexError:
raise StopIteration
# override some parse_** calls with the correct _scan_once
if nextchar == '"':
return parse_string(string, idx + 1, encoding, strict)
elif nextchar == '{':
return parse_object((string, idx + 1), encoding, strict,
_scan_once, object_hook, object_pairs_hook)
elif nextchar == '[':
return parse_array((string, idx + 1), _scan_once)
elif nextchar == 'n' and string[idx:idx + 4] == 'null':
return 'Cat', idx + 4
# invoke default scanner
return interal_scanner(string, idx)
return _scan_once
现在我们只需要一个JSONDecoder
将使用我们的扫描仪而不是默认扫描仪的子类:
class MyJSONDecoder(json.JSONDecoder):
def __init__(self, encoding=None, object_hook=None, parse_float=None,
parse_int=None, parse_constant=None, strict=True,
object_pairs_hook=None):
json.JSONDecoder.__init__(self, encoding, object_hook, parse_float, parse_int, parse_constant, strict, object_pairs_hook)
# override scanner
self.scan_once = make_my_scanner(self)
然后像这样使用它:
decoder = MyJSONDecoder()
print decoder.decode('{"field1":null, "field2": "data!"}')
旧答案,但如果您不关心另一个函数调用对性能的影响,则仍然有效:
你需要创建一个JSONDecoder
具有特殊性质的物体object_hook
method:
import json
def parse_object(o):
for key in o:
if o[key] is None:
o[key] = 'Cat'
return o
decoder = json.JSONDecoder(object_hook=parse_object)
print decoder.decode('{"field1":null, "field2": "data!"}')
# that will print: {u'field2': u'data!', u'field1': u'Cat'}
根据json 模块的 Python 文档 https://docs.python.org/2/library/json.html#json.JSONDecoder:
object_hook 是一个可选函数,将使用任何对象文字解码(字典)的结果来调用。将使用 object_hook 的返回值而不是字典。
So parse_object
将得到一个可以通过交换所有来操作的字典None
值与“猫”。返回的对象/字典将在输出中使用。