深入研究Python-Flask源码:flask_encoder中JSONEncoder(object)类

小编从事python-flask框架的后端开发,为了吃透它,小编会不断的深入研究源码,今天从 flask_encoder中JSONEncoder(object)类开始深入研究。

class JSONEncoder(object):
    """可扩展JSON <http://json.org>编码Python数据结构。
    默认支持以下对象和类型:
    +-------------------+---------------+
    | Python            | JSON          |
    +===================+===============+
    | dict              | object        |
    +-------------------+---------------+
    | list, tuple       | array         |
    +-------------------+---------------+
    | str               | string        |
    +-------------------+---------------+
    | int, float        | number        |
    +-------------------+---------------+
    | True              | true          |
    +-------------------+---------------+
    | False             | false         |
    +-------------------+---------------+
    | None              | null          |
    +-------------------+---------------+

    
    要扩展它以识别其他对象,可以使用子类和实现a''.default()方法,以及返回可序列化的另一个方法
    对象“o”,如果可能,它应该调用超类实现(抛出'TypeError')。
    """
    
    def __init__(self, *, skipkeys=False, ensure_ascii=True,check_circular=True, allow_nan=True, sort_keys=False,indent=None, separators=None, default=None):

        """如果skipkeys为false,那么尝试它就是一个类型错误对不是str、int、float或None的键进行编码。如果skipkeys是正确的,这样的项目只是跳过。

        如果ensure_ascii为真,则输出保证为str对象,所有传入的非ascii字符都转义。
如果ensure_ascii为false,则输出可以包含非ascii字符。
        
        如果check_circular为true,那么在编码期间,将检查列表、dicts和自定义编码对象,以查找循环引用,以防止无限递归(这会导致溢出错误)。
否则,不会进行此类检查。

        如果allow_nan为真,那么NaN、∞和-∞就会被编码成这样。这种行为不符合JSON规范,但与大多数基于JavaScript的编码器和解码器是一致的。否则,编码这样的浮点数将是一个ValueError。
        
        如果sort_keys为真,那么字典的输出将按键排序;这对于回归测试非常有用,可以确保每天都可以比较JSON序列化。

        如果indent是一个非负整数,那么JSON数组元素和对象成员将用缩进级别漂亮地打印出来。缩进级别为0只会插入换行符。没有一个是最紧凑的表示。

        如果specified,分隔符应该是(item_separator, key_separator)元组。默认值是(',',':').如果indent is None 和(',',':')。要获得最简洁的JSON表示,您应该指定(',',':')以消除空白。

        如果指定了默认值,则默认值是一个函数,用于调用无法序列化的对象。它应该返回一个JSON可编码版本的对象,或者引发一个“类型错误”。

        """初始化
        self.skipkeys = skipkeys
        self.ensure_ascii = ensure_ascii
        self.check_circular = check_circular
        self.allow_nan = allow_nan
        self.sort_keys = sort_keys
        self.indent = indent
        if separators is not None:
            self.item_separator, self.key_separator = separators
        elif indent is not None:
            self.item_separator = ','
        if default is not None:
            self.default = default

    def default(self, o):
        """在子类中实现此方法,使其返回可序列化的对象'o',或调用基本实现(引发'TypeError')。
例如,要支持任意迭代器,可以这样做实现默认如下::
            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                # 让基类默认方法引发类型错误
                return JSONEncoder.default(self, o)

        """
        raise TypeError("Object of type '%s' is not JSON serializable" %
                        o.__class__.__name__)

    def encode(self, o):
        """返回Python数据结构的JSON字符串表示形式.
        >>> from json.encoder import JSONEncoder
        >>> JSONEncoder().encode({"foo": ["bar", "baz"]})'{"foo": ["bar", "baz"]}'
        """
       # 这是非常简单的案例和基准测试。
        if isinstance(o, str):
            if self.ensure_ascii:
                return encode_basestring_ascii(o)
            else:
                return encode_basestring(o)
        # 这不会将迭代器直接传递到" .join(),因为异常没有那么详细。列表调用应该是大致与.join()            
        # 所做的PySequence_Fast等价。
        chunks = self.iterencode(o, _one_shot=True)
        if not isinstance(chunks, (list, tuple)):
            chunks = list(chunks)
        return ''.join(chunks)
    def iterencode(self, o, _one_shot=False):
        """对给定对象进行编码并产生每个字符串,表示是可用的。
        demo::
            for chunk in JSONEncoder().iterencode(bigobject):
                mysocket.write(chunk)
        """
        if self.check_circular:
            markers = {}
        else:
            markers = None
        if self.ensure_ascii:
            _encoder = encode_basestring_ascii
        else:
            _encoder = encode_basestring

        def floatstr(o, allow_nan=self.allow_nan,
                _repr=float.__repr__, _inf=INFINITY, _neginf=-INFINITY):
            # 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'
            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
        if (_one_shot and c_make_encoder is not None and self.indent is None):
            _iterencode = c_make_encoder(markers, self.default, _encoder, self.indent,
                self.key_separator, self.item_separator, self.sort_keys,
                self.skipkeys, self.allow_nan)
        else:
            _iterencode = _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)

小编发现,源码对于json的打包有默认的数据类型,但是,我们可以给他扩展其他类型,比如:decimal。

class JSONEncoder(_json.JSONEncoder):
    """默认的Flask JSON编码器。这个版本扩展了默认的simplejson编码器,支持“datetime”对象、“UUID”对象和“Markup”对象,这些对象被序列化为RFC 822 datetime字符串(与HTTP日期格式相同)。为了支持更多的数据类型,请重写:meth: ' default '方法。
    """

    def default(self, o):
        """在子类中实现此方法,使其返回可序列化的对象'o',或调用基本实现(引发'TypeError ')。
        例如,要支持任意迭代器,可以这样实现默认值::
            def default(self, o):
                try:
                    iterable = iter(o)
                except TypeError:
                    pass
                else:
                    return list(iterable)
                return JSONEncoder.default(self, o)
        """
        if isinstance(o, datetime):
            return http_date(o)
        if isinstance(o, uuid.UUID):
            return str(o)
        if hasattr(o, '__html__'):
            return text_type(o.__html__())
        if isinstance(o, Decimal):
            return o.__float__()
        return _json.JSONEncoder.default(self, o)

class Decimal(object):
    def __float__(self):
        if self.isnan():
            if self.is_nan():
                raise ValueError("Cannot convert signaling NaN to float")
            s = "-nan" if self._sign else "nan"
        else:
            s = str(self)
        return float(s)


    def _isnan(self):
        """返回数字是否为0
        0 if a number
        1 if NaN
        2 if sNaN
        """
        if self._is_sepcial:
            exp = self._exp
            if exp == 'n':
                return 1
            elif exp == 'N':
                return 2
        return 0

    def isnan(self):
        """如果是NaN,返回True, 否则,返回False"""
        return self._exp == 'N'



 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值