Python-Flaskソースコードの詳細研究:flask_EncoderにおけるJSONEncoder(object)クラス
7599 ワード
編集者はpython-flaskフレームワークのバックエンドの開発に従事して、それを食べるために、編集者は絶えずソースコードを深く研究して、今日flask_EncoderではJSONEncoder(object)クラスが深く研究を開始している.
編集者は、ソースコードがjsonのパッケージに対してデフォルトのデータ型があることを発見しましたが、decimalなどの他のタイプを拡張することができます.
class JSONEncoder(object):
""" JSON 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'