Python JSONDecoder自定义翻译null类型

标签 python json decode translate

在 python 中,JSONDecoder 默认将 null 转换为 None,如下所示。我怎样才能将 null -> None 的翻译更改为不同的东西。即 null -> 'Cat'

class json.JSONDecoder([encoding[, object_hook[, parse_float[, parse_int[, parse_constant[, strict[, object_pairs_hook]]]]]]])

Simple JSON decoder.

Performs the following translations in decoding by default:
  JSON  Python
  object    dict
  array     list
  string    unicode
  number (int)  int, long
  number (real)     float
  true  True
  false     False
  null  None

我愿意 json.loads({"field1":null, "field2": "data!"})

返回 {u'field2': u'data!', u'field1': u'Cat'}

最佳答案

2014 年 12 月 30 日更新

实现此目的的最简单方法是使用 JSONDecoderobject_hook 回调,如我在下面的旧答案中所述。但是,由于这需要对数据中的每个键值对进行额外的函数调用,因此这可能会对性能产生影响。

所以,如果你真的想改变 json 处理 None 的方式,你需要更深入地挖掘。 JSONDecoder 使用扫描器在 JSON 输入中查找某些标记。不幸的是,这是一个函数而不是一个类,因此子类化并不是那么容易。扫描仪函数称为 py_make_scanner,可以在 json/scanner.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!"}')

旧答案,但如果您不关心另一个函数调用的性能影响,它仍然有效:

您需要使用特殊的object_hook 方法创建一个JSONDecoder 对象:

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'}

根据Python documentation of the json module :

object_hook is an optional function that will be called with the result of any object literal decoded (a dict). The return value of object_hook will be used instead of the dict.

因此 parse_object 将获得一个字典,可以通过将所有 None 值与“Cat”交换来对其进行操作。然后将在输出中使用返回的对象/字典。

关于Python JSONDecoder自定义翻译null类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27695901/

相关文章:

python - wsgi - 处理客户端超时

python - 如何在 Flask-Bootstrap 中使用 Bootstrap 4?

php - 如何从数据库中获取嵌套 JSON 数组的数据?

ruby-on-rails - 出现错误 - 类型 "json"不存在 - 在 rake db 迁移期间在 Postgresql 中

python - openshift 上的 Django、python 非 ascii 字符

python - OLS 回归 python 中的形状未对齐错误

java - 调用 WebService Asp.Net 发送参数 JSON

Python 2.7 : how to prevent automatic decoding from hex to string

mysql - 安卓 :Retrieve Polyline From Mysql Database

python-3.x - 从 CSV 文件创建 Networkx Graph