# 【Python 筆記】JSON 格式讀寫 [TOC] 感謝您點進本篇文章,我是 LukeTseng,該系列主要以筆記加上口語白話形式學習 Python,若文章某處有誤敬請告知,非常感謝。 ## JSON 是啥? JSON 全名是 **J**ava**S**cript **O**bject **N**otation,這是一種輕量級的資料交換格式,以純文字方式儲存和傳輸資料。雖然名字有 javascript,但他完全獨立於這個程式語言,幾乎所有現代程式語言都支援 JSON 格式。 JSON 的語法很簡單,與 Python 中的字典相似,同樣是採用鍵值對(key-value)的方式組織資料。 JSON 由兩個主要結構組成: 1. 物件(Object)使用大括號 `{}` 包起來,含鍵值對。 2. 陣列(Array)使用中括號 `[]` 包裹,含有序的值列表。 ### JSON 的資料型態 JSON 支援六種資料型態,分為簡單型態和複雜型態: - 簡單型態: - 字串(string):必須用雙引號包裹,如 `"name": "LukeTseng"`。 - 數字(Number):可為整數或浮點數,如 `"age": 25` 或 `"price": 99.9`。 - 布林值(Boolean):只能是 `true` 或 `false`,不需要引號。 - 空值(Null):表示空值,使用 `null`。 - 複雜類型: - 物件(Object):無序的鍵值對集合,用大括號 `{}` 包起來。 - 陣列(Array):有序的值集合,用中括號 `[]` 包起來。 ### JSON 的範例 取自:https://json.org/example.html ``` { "menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } } } ``` ## JSON in Python Python 本身就有內建 JSON 的套件,使用 `import json` 這行程式碼即可使用。 這個套件主要就用到以下這四個函式: 1. `json.dumps()`:將 Python **物件**轉換成 JSON 字串。 2. `json.loads()`:將 JSON **字串**轉換成 Python 物件。 3. `json.dump()`:將 Python **物件**寫入 JSON 檔案。 4. `json.load()`:從 JSON 檔案讀取資料到 Python 物件。 上面四個函式其實是兩個函式,因為你會發現 dump 加一個 s 就是字串的意思。 下表關聯了 JSON 資料型態跟 Python 物件的關係: | Python | JSON | | -------- | -------- | | 字典(Dict) | 物件(Object) | | 列表(List) | 陣列(Array) | | 字串(String) | 字串(String) | | 數字(Number) | 數字(Number) | | True/False | true/false | | None | null | ### 1. json.dumps() 語法: ```python json.dumps(obj, skipkeys=False, ensure_ascii=True, allow_nan=True, indent=None, separators=None, sort_keys=False) ``` - obj:要轉換的 Python 物件(字典、列表、字串等)。 - skipkeys:跳過不可序列化的 key,而非引發錯誤。 - ensure_ascii:如果為 True(預設值),則跳脫(Escape)非 ASCII 字元;設為 False 則保留它們。 - allow_nan:允許特殊浮點數值(NaN、Infinity)。 - indent:縮排,可指定為某個數值。 - separators:更改預設分隔符號。 - sort_keys:按照字典序對字典鍵進行排序 範例(Python 字典轉 JSON): ```python= import json # Python Dict student = { "name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": ["演算法", "資料結構", "作業系統"], "level" : "SSR", } # 轉換成 JSON 字串 json_string = json.dumps(student) print(json_string) ``` Output: ``` {"name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": ["\u6f14\u7b97\u6cd5", "\u8cc7\u6599\u7d50\u69cb", "\u4f5c\u696d\u7cfb\u7d71"], "level": "SSR"} ``` 看來輸出遇到編碼問題了,那這時候只要把 `ensure_ascii = False` 就好了,因為他預設是開著的,所以會自動把非 ASCII 字元給轉成 Unicode 編碼。 再試一次: ```python= import json # Python Dict student = { "name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": ["演算法", "資料結構", "作業系統"], "level" : "SSR", } # 轉換成 JSON 字串 json_string = json.dumps(student, ensure_ascii=False) print(json_string) ``` Output: ``` {"name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": ["演算法", "資料結構", "作業系統"], "level": "SSR"} ``` 你會看到輸出是一行的,這時候可以用 indent 參數調整縮排,讓結果美化: ```python= import json # Python Dict student = { "name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": ["演算法", "資料結構", "作業系統"], "level" : "SSR", } # 轉換成 JSON 字串 json_string = json.dumps(student, ensure_ascii=False, indent=4) print(json_string) ``` Output: ``` { "name": "LukeTseng", "age": 18, "gpa": 4.3, "courses": [ "演算法", "資料結構", "作業系統" ], "level": "SSR" } ``` ### 2. json.loads() 語法: ``` json.loads(s) ``` - `s`:有效的 JSON 字串(可為 str、bytes 或 bytearray 類型) 範例: ```python= import json # 收到的 JSON 字串 json_data = """ {"menu": { "id": "file", "value": "File", "popup": { "menuitem": [ {"value": "New", "onclick": "CreateNewDoc()"}, {"value": "Open", "onclick": "OpenDoc()"}, {"value": "Close", "onclick": "CloseDoc()"} ] } }} """ # 轉成 Python 字典 menu = json.loads(json_data) print(menu) print(menu['menu']['id']) # file print(type(menu)) # <class 'dict'> ``` Output: ``` {'menu': {'id': 'file', 'value': 'File', 'popup': {'menuitem': [{'value': 'New', 'onclick': 'CreateNewDoc()'}, {'value': 'Open', 'onclick': 'OpenDoc()'}, {'value': 'Close', 'onclick': 'CloseDoc()'}]}}} file <class 'dict'> ``` ### 3. json.dump() 語法同 `json.dumps()`。 範例: ```python= import json # 準備要儲存的資料 students = [ {"name": "LukeTseng", "score": 100}, {"name": "陳圈翔", "score": 87}, {"name": "楊1停", "score": 11} ] # 寫入檔案 with open('students.json', 'w', encoding='utf-8') as file: json.dump(students, file, indent=4, ensure_ascii=False) ``` 若目錄沒有檔案的話會自動生成一份檔案,有的話則會覆寫整個檔案。 結果(`students.json`): ```jsonld= [ { "name": "LukeTseng", "score": 100 }, { "name": "陳圈翔", "score": 87 }, { "name": "楊1停", "score": 11 } ] ``` ### 4. json.load() 語法同 `json.loads()`。 範例: 沿用上一份範例生成的 `students.json`。 ```python= import json # 讀取檔案 with open('students.json', 'r', encoding='utf-8') as file: students = json.load(file) print(students) for student in students: print(f"{student['name']} 的分數是 {student['score']}") ``` Output: ``` [{'name': 'LukeTseng', 'score': 100}, {'name': '陳圈翔', 'score': 87}, {'name': '楊1停', 'score': 11}] LukeTseng 的分數是 100 陳圈翔 的分數是 87 楊1停 的分數是 11 ``` ## 總結 JSON 由兩個主要結構組成:物件(Object)使用大括號 `{}` 包起來,以及陣列(Array)使用中括號 `[]` 包起來。 JSON 支援六種資料型態: 簡單型態: * 字串(String):必須用雙引號包裹,如 `"name": "LukeTseng"` * 數字(Number):可為整數或浮點數 * 布林值(Boolean):只能是 `true` 或 `false` * 空值(Null):表示空值,使用 `null` 複雜型態: * 物件(Object):無序的鍵值對集合。 * 陣列(Array):有序的值集合。 ### Python 的 JSON 套件 Python 內建的 json 套件提供四個主要函式: * json.dumps():將 Python 物件轉換成 JSON 字串(s 代表 string) * json.loads():將 JSON 字串轉換成 Python 物件 * json.dump():將 Python 物件寫入 JSON 檔案 * json.load():從 JSON 檔案讀取資料到 Python 物件 Python 物件對應 JSON 資料型態關係: | Python | JSON | | -------- | -------- | | 字典(Dict) | 物件(Object) | | 列表(List) | 陣列(Array) | | 字串(String) | 字串(String) | | 數字(Number) | 數字(Number) | | True/False | true/false | | None | null | `json.dumps()` or `json.dump()` 常用參數: * `ensure_ascii`:預設為 True 會跳脫非 ASCII 字元,設為 False 可保留中文字元 * `indent`:設定縮排數值,美化輸出格式 * `sort_keys`:按字典序排序鍵 * `skipkeys`:跳過不可序列化的鍵 ## 參考資料 [json.loads() in Python - GeeksforGeeks](https://www.geeksforgeeks.org/python/json-loads-in-python/) [json.dumps() in Python - GeeksforGeeks](https://www.geeksforgeeks.org/python/json-dumps-in-python/) [Python3 JSON 数据解析 | 菜鸟教程](https://www.runoob.com/python3/python3-json.html) [JSON with Python - GeeksforGeeks](https://www.geeksforgeeks.org/python/json-with-python/) [JSON 檔案操作 - Python 教學 | STEAM 教育學習網](https://steam.oxxostudio.tw/category/python/library/json.html) [JSON Example](https://json.org/example.html)