日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > python >内容正文

python

python Json的一点收获,自定义序列化方法

發布時間:2023/12/9 python 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python Json的一点收获,自定义序列化方法 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

From: http://blog.csdn.net/jlnuboy/article/details/5732196

PyMOTW: json

  • 模塊: json
  • 目的: JavaScript對象格式序列器
  • python版本: 2.6

json模塊提供了一個類似于pickle中用于轉換內存中python對象為一個序列表示形式(“JavaScript Object Notation”)的API接口. 但和pickle不同的是, JSON在其他很多語言中都有對應實現(特別是在JavaScript中), 使其更適用于內部應用間的通信. 在一個AJAX應用中, JSON可能對于web服務器和客戶端間的通信, 使用最為廣泛, 但它也不僅限于這類應用.

?

?

?

簡單數據類型的編碼和解碼

編碼器默認支持Python的本地類型(如int, float, list, tuple, dict).

?

?

[python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • print?'DATA:',?repr(data)??
  • data_string?=?json.dumps(data)??
  • print?'JSON:',?data_string??
  • ?

    編碼器處理之后的值和Python的repr()的輸出值很類似.

    [python] view plaincopy
  • $?python?json_simple_types.py??
  • DATA:?[{'a':?'A',?'c':?3.0,?'b':?(2,?4)}]??
  • JSON:?[{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]??
  • ?

    編碼之后的解碼所獲的的值可能和原先的對象不是完全一致.

    [python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • data_string?=?json.dumps(data)??
  • print?'ENCODED:',?data_string??
  • decoded?=?json.loads(data_string)??
  • print?'DECODED:',?decoded??
  • print?'ORIGINAL:',?type(data[0]['b'])??
  • print?'DECODED?:',?type(decoded[0]['b'])??
  • ?

    比如說, 元組會被轉換為JSON的列表.

    [python] view plaincopy
  • $?python?json_simple_types_decode.py??
  • ENCODED:?[{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]??
  • DECODED:?[{u'a':?u'A',?u'c':?3.0,?u'b':?[2,?4]}]??
  • ORIGINAL:?<type?'tuple'>??
  • DECODED?:?<type?'list'>??
  • ?

    ?

    人性化使用 vs 緊湊型輸出

    JSON優于pickle的另外一點是其結果具有可讀性. dumps()函數接收多個參數用于更好的輸出結構. 比如說. sort_keys參數告訴編碼器按照順序輸出字典的鍵值, 而不是隨機無序的.

    [python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • print?'DATA:',?repr(data)??
  • unsorted?=?json.dumps(data)??
  • print?'JSON:',?json.dumps(data)??
  • print?'SORT:',?json.dumps(data,?sort_keys=True)??
  • first?=?json.dumps(data,?sort_keys=True)??
  • second?=?json.dumps(data,?sort_keys=True)??
  • print?'UNSORTED?MATCH:',?unsorted?==?first??
  • print?'SORTED?MATCH?:',?first?==?second??
  • ?

    排序之后更容易讓人看出結果, 也使進行JSON的比較輸出成為可能.

    ?

    [python] view plaincopy
  • $?python?json_sort_keys.py??
  • DATA:?[{'a':?'A',?'c':?3.0,?'b':?(2,?4)}]??
  • JSON:?[{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]??
  • SORT:?[{"a":?"A",?"b":?[2,?4],?"c":?3.0}]??
  • UNSORTED?MATCH:?False??
  • SORTED?MATCH?:?True??
  • ?

    對于高度嵌套的數據結構, 你會想在輸出結果中增加縮進以更好的顯示其格式.

    [python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • print?'DATA:',?repr(data)??
  • print?'NORMAL:',?json.dumps(data,?sort_keys=True)??
  • print?'INDENT:',?json.dumps(data,?sort_keys=True,?indent=2)??
  • ?

    當indent參數是一非負整數時, 輸出的結構和pprint更為接近, 在每個縮進層次上都有前導空格.

    [python] view plaincopy
  • $?python?json_indent.py??
  • DATA:?[{'a':?'A',?'c':?3.0,?'b':?(2,?4)}]??
  • NORMAL:?[{"a":?"A",?"b":?[2,?4],?"c":?3.0}]??
  • INDENT:?[??
  • ?????????????{??
  • ?????????????"a":?"A",??
  • ?????????????"b":?[??
  • ??????????????????????2,??
  • ??????????????????????4??
  • ??????????????????????],??
  • ?????????????"c":?3.0??
  • ?????????????}??
  • ]??
  • ?

    像這種類型輸出的數據在傳輸過程中需占用更多的字節, 不過, 在實際生產環境中沒有必要使用縮進格式. 實際上, 你可以設置數據的分隔符來讓結果更為緊湊.

    [python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • print?'DATA:',?repr(data)??
  • print?'repr(data)?:',?len(repr(data))??
  • print?'dumps(data)?:',?len(json.dumps(data))??
  • print?'dumps(data,?indent=2)?:',?len(json.dumps(data,?indent=2))??
  • print?'dumps(data,?separators):',?len(json.dumps(data,?separators=(',',':')))??
  • ?

    dumps()函數的separators參數是一個元組, 包含分隔列表各項和字典鍵值各項的字符串. 默認是(‘, ‘, ‘: ‘). 可以去掉后者中的空格, 我們可以得到較緊湊的輸出.

    [python] view plaincopy
  • $?python?json_compact_encoding.py??
  • DATA:?[{'a':?'A',?'c':?3.0,?'b':?(2,?4)}]??
  • repr(data)?:?35??
  • dumps(data)?:?35??
  • dumps(data,?indent=2)?:?76??
  • dumps(data,?separators):?29??
  • ?

    ?

    編碼字典

    JSON格式中, 字典的鍵被限制為字符串類型. 如果字典中的鍵是其他類型, 那么在編碼這個對象時會產生一個TypeError異常. 一種解決這個限制的方法是, 在編碼時, 使用skipkeys參數跳過所有非字符串類型的鍵.

    [python] view plaincopy
  • import?json??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0,?('d',):'D?tuple'?}?]??
  • print?'First?attempt'??
  • try:??
  • ????print?json.dumps(data)??
  • except?TypeError,?err:??
  • ????print?'ERROR:',?err??
  • print??
  • print?'Second?attempt'??
  • print?json.dumps(data,?skipkeys=True)??
  • ?

    非字符串類型的鍵被忽略, 而不拋出一個異常.

    [python] view plaincopy
  • $?python?json_skipkeys.py??
  • First?attempt??
  • ERROR:?key?('d',)?is?not?a?string??
  • Second?attempt??
  • [{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]??
  • ?

    ?

    自定義類型的處理

    上面所有的例子都是用了Python的內置類型作為例子, 因為他們都被json本身支持. 當然, 自定義類型也常常需要正確編碼. 這里有兩種情況:

    第一, 對于一個類的編碼:

    [python] view plaincopy
  • class?MyObj(object):??
  • ????def?__init__(self,?s):??
  • ????????self.s?=?s??
  • ????def?__repr__(self):??
  • ????????return?'<MyObj(%s)>'?%?self.s??
  • ?

    編碼一個MyObj對象的最簡單方式是定義個轉換函數, 用于將位置類型轉換出呢個已知類型. 你沒有必要自己進行編碼, 而僅需要將一個對象轉換成另一個對象.

    [python] view plaincopy
  • import?json??
  • import?json_myobj??
  • obj?=?json_myobj.MyObj('instance?value?goes?here')??
  • print?'First?attempt'??
  • try:??
  • ????print?json.dumps(obj)??
  • except?TypeError,?err:??
  • ????print?'ERROR:',?err??
  • def?convert_to_builtin_type(obj):??
  • ????print?'default(',?repr(obj),?')'??
  • ????#?Convert?objects?to?a?dictionary?of?their?representation??
  • ????d?=?{?'__class__':obj.__class__.__name__,??
  • ??????????'__module__':obj.__module__,??
  • ????????}??
  • ????d.update(obj.__dict__)??
  • ????return?d??
  • print??
  • print?'With?default'??
  • print?json.dumps(obj,?default=convert_to_builtin_type)??
  • ?

    在convert_to_builtin_type()函數中, 不被json識別的類對象被轉換成一個包含足夠能重建這個對象的字典信息.

    [python] view plaincopy
  • $?python?json_dump_default.py??
  • First?attempt??
  • ERROR:?<MyObj(instance?value?goes?here)>?is?not?JSON?serializable??
  • With?default??
  • default(?<MyObj(instance?value?goes?here)>?)??
  • {"s":?"instance?value?goes?here",?"__module__":?"json_myobj",?"__class__":?"MyObj"}??
  • ?

    ?

    為了能解碼結果數據并創建一個MyObj實例, 我們需要配合解碼器以便可以從模塊中導入類并創建實例. 我們在loads()函數中使用object_hook參數.

    在輸入數據流中, 對于解碼獲得的每個字典都會調用object_hook, 將這個字典轉換成其他類型的對象. hook函數返回的是調用程序所需要的對象, 而不是字典.

    [python] view plaincopy
  • import?json??
  • def?dict_to_object(d):??
  • ????if?'__class__'?in?d:??
  • ????????class_name?=?d.pop('__class__')??
  • ????????module_name?=?d.pop('__module__')??
  • ????????module?=?__import__(module_name)??
  • ????????print?'MODULE:',?module??
  • ????????class_?=?getattr(module,?class_name)??
  • ????????print?'CLASS:',?class_??
  • ????????args?=?dict(?(key.encode('ascii'),?value)?for?key,?value?in?d.items())??
  • ????????print?'INSTANCE?ARGS:',?args??
  • ????????inst?=?class_(**args)??
  • ????else:??
  • ????????inst?=?d??
  • ????return?inst??
  • encoded_object?=?'[{"s":?"instance?value?goes?here",?"__module__":?"json_myobj",?"__class__":?"MyObj"}]'??
  • myobj_instance?=?json.loads(encoded_object,?object_hook=dict_to_object)??
  • print?myobj_instance??
  • ?

    由于json將字符串值轉換成unicode對象, 所以我們需要將作為類構造器的參數重新編碼為ASCII字符串.

    [python] view plaincopy
  • $?python?json_load_object_hook.py??
  • MODULE:?<module?'json_myobj'?from?'/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/json/json_myobj.pyc'>??
  • CLASS:?<class?'json_myobj.MyObj'>??
  • INSTANCE?ARGS:?{'s':?u'instance?value?goes?here'}??
  • [<MyObj(instance?value?goes?here)>]??
  • ?

    ?

    對于內置類型也都有類似的hooks, 如整型(parse_int), 浮點型(parse_float), 常量(parse_constant).

    編碼和解碼類

    除了上述的這些函數外, json模塊還提供了編碼和解碼類. 直接使用這些類, 你可以訪問到額外的API接口或者定制創建它的子類.

    JSONEncoder提供了一個產生編碼數據”塊”的的迭代接口, 這在寫入一個文件或網絡sockets時(不需要在內存中完整表示整個數據)是非常方便的,

    [python] view plaincopy
  • import?json??
  • encoder?=?json.JSONEncoder()??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • for?part?in?encoder.iterencode(data):??
  • ????print?'PART:',?part??
  • ?

    正如你看到的, 數據是以邏輯單位形式輸出的, 而不是按照數據長度輸出.

    [python] view plaincopy
  • $?python?json_encoder_iterable.py??
  • ?????PART:?[??
  • ?????????????PART:?{??
  • ?????????????PART:?"a"??
  • ?????????????PART:?:??
  • ?????????????PART:?"A"??
  • ?????????????PART:?,??
  • ?????????????PART:?"c"??
  • ?????????????PART:?:??
  • ?????????????PART:?3.0??
  • ?????????????PART:?,??
  • ?????????????PART:?"b"??
  • ?????????????PART:?:??
  • ?????????????PART:?[??
  • ?????????????PART:?2??
  • ?????????????PART:?,??
  • ?????????????PART:?4??
  • ?????????????PART:?]??
  • ?????????????PART:?}??
  • ?????????????PART:?]??
  • ?

    ?

    encode()方法基本上等價于’‘.join(encoder.iterencode()), 只是多了些附加錯誤檢查.

    為了能夠編碼任何類型的對象, 我們可以編寫一類似于上述的convert_to_builtin_type()函數去重載default()方法.

    [python] view plaincopy
  • import?json??
  • import?json_myobj??
  • class?MyEncoder(json.JSONEncoder):??
  • ????def?default(self,?obj):??
  • ????????print?'default(',?repr(obj),?')'??
  • ????????#?Convert?objects?to?a?dictionary?of?their?representation??
  • ????????d?=?{?'__class__':obj.__class__.__name__,??
  • ??????????????'__module__':obj.__module__,??
  • ????????????}??
  • ????????d.update(obj.__dict__)??
  • ????????return?d??
  • obj?=?json_myobj.MyObj('internal?data')??
  • print?obj??
  • print?MyEncoder().encode(obj)??
  • ?

    這里輸出的結果是和先前的實現一致的.

    [python] view plaincopy
  • $?python?json_encoder_default.py??
  • <MyObj(internal?data)>??
  • default(?<MyObj(internal?data)>?)??
  • {"s":?"internal?data",?"__module__":?"json_myobj",?"__class__":?"MyObj"}??
  • ?

    解碼后將字典轉換成一個對象, 在先前實現的基礎上稍作修改即可.

    [python] view plaincopy
  • import?json??
  • class?MyDecoder(json.JSONDecoder):??
  • ????def?__init__(self):??
  • ????????json.JSONDecoder.__init__(self,?object_hook=self.dict_to_object)??
  • ????def?dict_to_object(self,?d):??
  • ????????if?'__class__'?in?d:??
  • ????????????class_name?=?d.pop('__class__')??
  • ????????????module_name?=?d.pop('__module__')??
  • ????????????module?=?__import__(module_name)??
  • ????????????print?'MODULE:',?module??
  • ????????????class_?=?getattr(module,?class_name)??
  • ????????????print?'CLASS:',?class_??
  • ????????????args?=?dict(?(key.encode('ascii'),?value)?for?key,?value?in?d.items())??
  • ????????????print?'INSTANCE?ARGS:',?args??
  • ????????????inst?=?class_(**args)??
  • ????????else:??
  • ????????????inst?=?d??
  • ????????return?inst??
  • encoded_object?=?'[{"s":?"instance?value?goes?here",?"__module__":?"json_myobj",?"__class__":?"MyObj"}]'??
  • myobj_instance?=?MyDecoder().decode(encoded_object)??
  • print?myobj_instance??
  • ?

    輸出結果也是和先前例子中輸出的一樣.

    [python] view plaincopy
  • $?python?json_decoder_object_hook.py??
  • MODULE:?<module?'json_myobj'?from?'/Users/dhellmann/Documents/PyMOTW/src/PyMOTW/json/json_myobj.pyc'>??
  • CLASS:?<class?'json_myobj.MyObj'>??
  • INSTANCE?ARGS:?{'s':?u'instance?value?goes?here'}??
  • [<MyObj(instance?value?goes?here)>]??
  • ?

    ?

    流和文件的處理

    到目前為止的所有例子, 我們都假設待編碼的數據都是一次性完整加載到內存中的. 但對于大型數據結構來說, 將編碼數據直接寫入一個類文件對象, 可能會更好. load()和dump()函數可以接收一個用于讀或寫的類文件對象的引用.

    [python] view plaincopy
  • import?json??
  • import?tempfile??
  • data?=?[?{?'a':'A',?'b':(2,?4),?'c':3.0?}?]??
  • f?=?tempfile.NamedTemporaryFile(mode='w+')??
  • json.dump(data,?f)??
  • f.flush()??
  • print?open(f.name,?'r').read()??
  • ?

    對于socket來說, 也和正常文件句柄類似.

    [python] view plaincopy
  • $?python?json_dump_file.py??
  • [{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]??
  • ?

    雖然一次性讀取部分數據不是很好, 但是load()函數仍然提供了從流數據輸入中封裝生成對象的功能.

    [python] view plaincopy
  • import?json??
  • import?tempfile??
  • f?=?tempfile.NamedTemporaryFile(mode='w+')??
  • f.write('[{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]')??
  • f.flush()??
  • f.seek(0)??
  • print?json.load(f)??
  • ? [python] view plaincopy
  • $?python?json_load_file.py??
  • [{u'a':?u'A',?u'c':?3.0,?u'b':?[2,?4]}]??
  • ?

    ?

    混合數據流

    JSONDecoder包含了raw_decode()方法, 用于解碼在很多數據組成的數據結構, 例如包含多余文本的JSON數據. 返回的值是從輸入數據中解碼獲得的對象, 數據中的index表示解碼對象結束時所在的位置.

    [python] view plaincopy
  • import?json??
  • decoder?=?json.JSONDecoder()??
  • def?get_decoded_and_remainder(input_data):??
  • ????obj,?end?=?decoder.raw_decode(input_data)??
  • ????remaining?=?input_data[end:]??
  • ????return?(obj,?end,?remaining)??
  • encoded_object?=?'[{"a":?"A",?"c":?3.0,?"b":?[2,?4]}]'??
  • extra_text?=?'This?text?is?not?JSON.'??
  • print?'JSON?first:'??
  • obj,?end,?remaining?=?get_decoded_and_remainder('?'.join([encoded_object,?extra_text]))??
  • print?'Object?:',?obj??
  • print?'End?of?parsed?input?:',?end??
  • print?'Remaining?text?:',?repr(remaining)??
  • print??
  • print?'JSON?embedded:'??
  • try:??
  • ????obj,?end,?remaining?=?get_decoded_and_remainder(??
  • ?????????????????'?'.join([extra_text,?encoded_object,?extra_text])??
  • ?????????????????)??
  • except?ValueError,?err:??
  • ????print?'ERROR:',?err??
  • ?

    不幸的是, 這僅僅在對象出現在輸入流的開始處才有效.

    [python] view plaincopy
  • $?python?json_mixed_data.py??
  • JSON?first:??
  • Object?:?[{u'a':?u'A',?u'c':?3.0,?u'b':?[2,?4]}]??
  • End?of?parsed?input?:?35??
  • Remaining?text?:?'?This?text?is?not?JSON.'??
  • JSON?embedded:??
  • ERROR:?No?JSON?object?could?be?decoded??


  • 總結

    以上是生活随笔為你收集整理的python Json的一点收获,自定义序列化方法的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。