是否有python解码器生成VALID json并处理NaN

时间:2017-10-12 14:56:57

标签: python json mongodb bson

我想在mthon中将mongoDb的输出序列化为实际的VALID json。我找到了几个库,但似乎没有一个生成有效的json 处理不兼容的值为null (未定义也可以。)

示例输入

{
    "_id" : ObjectId("57f3e32c71285f85b46d6fb5"),
    "rate" : Infinity
    "value" : NaN
}

预期输出

(尝试了json.dumps及其allow_nan选项,但它会抛出错误而且根本没有帮助)

{
    "_id" : { $oid: "57f3e32c71285f85b46d6fb5" },
    "rate" : null,
    "value" : null
}

任何人都知道方法/图书馆来实现这个目标吗?

作为一个例子,Javascript的JSON做得很好:

Object {_id: "57f3e32c71285f85b46d6fb5", rate: Infinity, value: NaN}
JSON.stringify(tg)
"{"_id":"57f3e32c71285f85b46d6fb5","rate":null,"value":null}"

1 个答案:

答案 0 :(得分:2)

你总是可以制作自己的编码器(我从https://gist.github.com/pauloalem/6244976偷走了这个编码器)

import json


class FloatEncoder(json.JSONEncoder):
    def __init__(self, nan_str="null", **kwargs):
        super(FloatEncoder, self).__init__(**kwargs)
        self.nan_str = nan_str

    def iterencode(self, o, _one_shot=False):
        """Encode the given object and yield each string
        representation as available.

        For example::

            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = json.encoder.encode_basestring_ascii
        else:
            _encoder = json.encoder.encode_basestring
        # if self.encoding != 'utf-8':
        #     def _encoder(o, _orig_encoder=_encoder, _encoding=self.encoding):
        #         if isinstance(o, str):
        #             o = o.decode(_encoding)
        #         return _orig_encoder(o)

        def floatstr(o, allow_nan=self.allow_nan, _repr=json.encoder.encode_basestring,
                _inf=json.encoder.INFINITY, _neginf=-json.encoder.INFINITY,
                nan_str=self.nan_str):
            # Check for specials.  Note that this type of test is processor
            # and/or platform-specific, so do tests which don't depend on the
            # internals.

            if o != o:
                text = nan_str
            elif o == _inf:
                text = 'Infinity'
            elif o == _neginf:
                text = '-Infinity'
            else:
                return _repr(o)

            if not allow_nan:
                raise ValueError(
                    "Out of range float values are not JSON compliant: " +
                    repr(o))

            return text

        _iterencode = json.encoder._make_iterencode(
                markers, self.default, _encoder, self.indent, floatstr,
                self.key_separator, self.item_separator, self.sort_keys,
                self.skipkeys, _one_shot)
        return _iterencode(o, 0)


d = {"i_will_byte_you_in_the_ass": float("NaN")}
print( json.dumps(d, cls=FloatEncoder) )