# JSON 學完了怎麼開關編輯檔案,這裡介紹一個常見的資料格式,許多程式的資料庫或資料顯示方式都是 JSON JSON 是 JavaScript Object Notation 的簡稱,JavaScript 是目前最普遍的寫網頁用的語言,object notation 就是指在 JavaScript 這個語言裡,object 的形式幾乎就是 JSON 的形狀。許多網頁資料庫就是用 JSON 寫。 而很幸運地,Python 要處理 JSON 也非常容易。 [json官網在這]( https://www.json.org/json-en.html) 簡單來說,json 就是一個大 dictionary。 複雜來說,它是一個 a format of strings,一個裝了無限個 dictionary 和 list 的 dictionary。 --- ### For example, 以下是一個 json 檔實際運用的例子,在我的疫情bot裡,許多功能都會需要每日確診的資料,因為每一次需要資料時都重新上網抓很麻煩,所以我們決定把資料一次抓下來,讓需要用到的地方讀我們自己的資料庫就好 ``` json { "today_confirmed": 0, "today_domestic": 0, "today_imported": 0, "today_deaths": "26", "additional_text": "\n今日新增之16,524例本土病例", "error": false } ``` 可以看到最外層是一組大括號,跟 dictionary 一樣 裡面也是一個 key 加 一個 value,跟 dictionary 一樣 下面是另一個我的疫情bot有用到的 json,這一個檔名叫 `history_data.json`,用來製作統計圖表的。 因為程式每天都會被重新跑一次,所以前一天的資料沒有辦法只存在程式記憶體 -- 也就是任何 variable 裡,於是我們用一個外部的檔案作為資料庫。 ``` json { "confirmed": [ 50, 25, 50, 25, 55187, 94808, 0, 0, 10000, 8822, 49, 0, 1000, 104 ], "average": [ 21449, 21442, 22867, 24120, 24123, 16239, 2838, 2853, 2996, 1582, 326, 320, 323, 187 ], "dates": [ "1015", "1014", "1013", "1012", "1011", "1010", "1009", "1008", "1007", "1006", "1005", "1004", "1003", "1002" ] } ``` 可以看到最外依然是 dictionary 的起手勢,但比較特別的是,這次的 value 是一個 list --- ### Step by step... 有基礎的概念之後,使用方式跟一般的 Python file I/O 差不多,只是我們可以用 Python 的 json library 來方便控制每一項 以上面的 `histiry_data.json` 為例 讀檔會跟一般讀檔一樣 ``` python import json with open("history_data.json", "r") as jsonFile1: history = json.load(jsonFile1) ``` 這裡 `with open("history_data.json", "r") as jsonFile1` 和 `jsonFile1 = open("history_data.json", "r")` 一樣,差別是後者最後需要 `jsonFile1.close()` 而前者不用。 接著 `json.load(jsonFile1)` 叫了一開始 import 進來的 json module,並使用了它的 `load()` function,最後這個 function 的 return 是一個 Python 看得懂的 json 格式,我們把它塞進一個名為 hostory 的 variable。 從這一刻起,hisotry 就不是一般讀檔讀進來的一堆純文字,而是一個 Python 的 json object Python 對於 json 最友善的部份就是我們完全可以把讀進來的 json 檔當作 dictionary 用 ``` python confirmed_history_list = history["confirmed"] average_history_list = history["average"] dates_history_list = history["dates"] ``` 就像用 key 讀取 dict 的 value 一樣,上面讀了 confirmed 和 average 這兩個 key 的 value,這兩個 value 不是單一數值而是一個 list,但仍然可以分別塞近 variable 裡,變成一般的 list 接著繼續 ``` python confirmed_history_list.pop() average_history_list.pop() dates_history_list.pop() #-------------------------------------- confirmed_history_list.insert(0, today_confirmed) today_average = int(statistics.mean(confirmed_history_list[:7])) average_history_list.insert(0, today_average) dates_history_list.insert(0, today_date) ``` 上面第一部份是簡單地把 list 的最後一項刪除 第二部份用了 Python list 的 `insert()` function (也是我當下搜尋才知道有這個東西),憑直覺地,可以看出 `insert()` 這個 funciton 的第一個 argument 應該代表想要插入的 index,而第二個代表想插入的值 於是這一段我把 list 的尾巴刪掉,從頭補了新的一項進去 也就是把當天的資料加入資料庫,然後把超過兩星期的過時資料刪掉了 但到目前為止 confirmed_history_list, average_history_list, 和 dates_history_list 都是我的 variable,與我的檔案無關,所以還需要把這些更新後的資料重新寫入檔案內 ``` python history["confirmed"] = confirmed_history_list history["average"] = average_history_list history["dates"] = dates_history_list with open("history_data.json", "w", encoding='utf-8') as jsonFile2: json.dump(history, jsonFile2, indent=4) ``` 上半部我們借用之前的 history 這個 json object,覆蓋掉它原本的值,把原本 key 是 confirmed, average, 和 dates 的 value 換成新的、改過的 list 下半部我們重開了一個可以寫入的 stream,然後用 json 的 `dump()` function 把更新後的 json object 整包塞到檔案 這就是說基礎不基礎,說複雜不複雜的 json 基本用法~ --- ### 實際運用 這裡是一個政府的開放資訊平台的資訊 https://data.gov.tw/dataset/156914 很多(或大部分)的個人 project 都會用到各種政府開放資訊,常見的格式有 txt, json, 和 csv,我個人最喜歡的格式就是 json。 現在可以來玩玩看開放資訊囉 ###### by json王 XD <br></br> :::info [BACK](https://hackmd.io/@lhsueh1/python101) :::