小编从事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'