深入研究Python-Flask原始碼:flask_encoder中JSONEncoder(object)類
阿新 • • 發佈:2018-12-10
小編從事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)