資料格式與結構化資料
從冗長的 API 回應擷取需要的欄位
使用工具
你想把 API 回應中的商品名稱放進會議筆記。搜尋 name 一開始很方便,但回應中也可能有顧客的 name,或某件商品沒有該欄位。手動複製就容易出錯,因此需要同時指定欄位及其所屬位置。
以下使用虛構商品清單。JSONPath 用來選取指定位置的值,不必改寫原資料。不必一開始就寫複雜運算式,可以從整體、清單、單筆再到名稱逐步縮小範圍,這樣結果為空時也容易找出問題。
提供已取得的本文,而不是 URL
這不是 API 用戶端,不會存取貼上的 URL、登入或尋找下一頁。請準備回應本文,只輸入 JSON 部分,HTTP 狀態列與標頭不是 JSON。分享範例時,用同結構的虛構資料取代含真實姓名或 Token 的正式回應,更容易重現與說明。
結果針對目前輸入,不是即時 API。伺服器之後更新,結果不會自動重新整理。若調查涉及資料新舊,應在自己的工作紀錄中標明檢查了哪份回應,將取得來源與擷取 JSON 分成兩個階段。
準備同時含商品名與負責人名的資料
{"items":[{"id":"A","name":"Notebook","price":500},{"id":"B","name":"Pencil","price":120},{"id":"C","name":null,"price":300}],"owner":{"name":"Demo team"},"page":1}開啟 JSONPath 擷取,把範例放進 JSON 輸入欄,再在獨立的運算式欄輸入 $ 並執行,即可將整份文件選為一個結果。如果此時出錯,應先檢查 JSON 括號與引號。不要把運算式接在 JSON 後面貼進同一欄,否則輸入就不是一份 JSON 文件。
結果外面有陣列,不代表原資料被改成了陣列。工具回傳的是所選值的清單;選中整份文件,就得到含一個元素的結果清單。要區分結果外層陣列與原資料中的 items 陣列,之後遇到兩層方括號就不會混淆。
先選第一筆,再擷取名稱
$.items[0].name["Notebook"]$ 表示整份文件,items 是其下的清單,[0] 選中第一筆,name 再選該商品的欄位。索引從 0 而非 1 開始,改為 [1] 得到 Pencil,[2] 得到 null。每次改數字都對照原資料位置,比死記運算式更容易理解路徑。
如果完整路徑取不到值,可以依序測試 $.items 與 $.items[0]。欄位拼字與大小寫都應與原資料一致,不要在 items 與 Items 之間猜測,而應檢查原文。結果為空不代表需要修改 JSON 中的欄位名稱。
用 * 取代逐筆複製
$.items[*].name["Notebook","Pencil",null]把 [0] 改成 [*],就會對清單各筆執行相同選取。路徑限定在 items 內,因此不包含 owner.name。與全文搜尋 name 不同,運算式本身保留了「商品清單中的名稱」這個條件,之後處理同類回應也容易說明擷取範圍。
結果有三筆,不代表伺服器總共只有三件商品。範例雖有 page 欄位,工具卻不會取得下一頁,只能處理你提供的回應。若需要完整匯出,還要另外檢查原 API 的分頁與筆數限制。
[] 與 [null] 看似都空,卻不同
$.items[2].name 得到 [null],因為第三筆有 name 欄位,其值為 null。$.items[3].name 得到 [],因為第四筆不存在。前者選到一個值,後者沒有選到值。若都報告成「值為 null」,就無法區分明確的 null 與缺少資料。
{"items":[]}對這份獨立範例執行 $.items,會得到 [[]],因為選中的是一個空陣列值。$.items[*] 則得到 [],因為陣列內部沒有元素。與其數方括號,不如思考「什麼被當作一個值選中」。空結果本身不代表運算式錯誤。
分別擷取名稱與價格,可能錯位
{"items":[{"id":"A","name":"Notebook","price":500},{"id":"B","price":120},{"id":"C","name":"Eraser","price":300}]}擷取名稱得到 Notebook 與 Eraser 兩筆,擷取價格得到 500、120、300 三筆。如果把第二個名稱與第二個價格橫向拼接,就會誤把 Eraser 的價格寫成 120。不要假設缺少欄位會自動補空位,結果數量不同本身就有意義。
需要保留名稱與價格的關係時,可用 $.items[*] 擷取完整商品物件,同時保留 id。轉成表格時,應將同一物件的欄位轉成欄,而不是依列號拼接兩份獨立清單。使用 JSON 與 CSV 轉換時,也要確認缺少欄位與 null 的表示方式。
遞迴搜尋 name 適合調查結構
$..name回到最初的 JSON 執行此式,還會找到 Demo team。遞迴搜尋適合尋找未知深度的同名欄位,但只看結果值不容易知道來源。可以先廣泛調查,確認目標層級後再縮小到 $.items[*].name。
不要對不必要的大資料使用過寬的遞迴搜尋。工具有結果筆數等限制,超過限制不代表會回傳縮短但完整的結果。先在包含目標結構的小範例驗證運算式,再套用到實際輸入,便於區分路徑錯誤與處理量問題。
網路範例無法執行時,先確認支援範圍
JSONPath 既有標準規範,也有實作擴充。SheepDev 不執行任意程式碼,並拒絕篩選與腳本運算式,因此其他網站用於篩選價格的運算式不一定能直接使用。不支援的運算式執行失敗,不等於符合條件的商品為零。
擷取結束後,檢查原資料範圍、所選欄位與結果筆數。分享時附上運算式與範圍,比只說「有兩個商品名」更清楚。例如「從本頁 items 中擷取到兩個存在的 name 值」,方便之後追查缺少資料或混入其他層級的問題。