# 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)
:::