當我第一次編寫一個重要的JSONPath 表達式時,我在它工作之前弄錯了三次,我只知道它是錯誤的,因為我配置的API 網關返回了一個空策略而不是我想要的字段。沒有反饋循環。我會編輯表達式、重新部署並等待。一旦我開始在另一個選項卡中保持 JSONPath 測試器打開,同樣的工作就需要兩分鐘而不是一個下午。本指南是關於我如何使用 JSONPath 測試儀 在 toolz。dev 上,語法實際執行的內容以及形成表達式的小陷阱在您確定它應該匹配時不會返回任何內容。
TL;DR: JSONPath 是 JSON 的查詢語言,就像 XPath 是 XML 一樣。 JSONPath 測試人員會評估類似的表達式
$.store.book[*].author針對文件並傳回每個匹配值及其路徑。這 JSONPath 測試儀 完全在瀏覽器中執行此操作,支援通配符、遞歸下降、切片、並集和過濾表達式,因此您可以在將真實資料貼上到程式碼之前建立查詢並對其進行調試。
什麼是 JSONPath?
JSONPath 是一種緊湊的語法,用於選擇 JSON 文件的部分內容。您編寫一條短路徑來描述資料中的路由,並評估它會傳回該路由處的一個或多個值。這個想法來自於 Stefan Goessner's 2007 年提案,它故意鏡像 XPath,以便任何查詢過 XML 的人都會有賓至如歸的感覺。多年來,沒有正式的規範,只有那篇文章和一系列基本上達成一致的實現,IETF 於 2024 年初發布 RFC 9535 把語法固定下來。
您遇到 JSONPath 的次數比您想像的要多。它是 Kubernetes 中的 Postman 和 Karate 等 API 測試工具中的選擇器語言 kubectl 在 AWS CloudWatch 和 Step Functions、日誌處理器以及數十個低程式碼平台中進行輸出格式化,使用者需要從 Webhook 有效負載中提取一個字段,而無需編寫程式碼。學習它一旦對所有這些都得到回報。
心理模型很簡單。 JSON 文件是一棵樹。物件有命名的分支,數組有編號的分支,葉子是你的標量值。 JSONPath 表達式是行走該樹的一組方向,結果是您落在的每個葉子或子樹。它的強大之處在於單一表達式可以同時落在許多地方。
JSONPath 測試儀實際上做什麼?
測試人員接受兩個輸入,即 JSON 和一個表達式,並向您顯示表達式選擇的每個節點。這聽起來很明顯,但該值位於回饋中。當表達式不傳回任何內容或傳回的次數超出您的預期時,測試人員會將猜謎遊戲變成兩秒檢查,因為您可以準確地看到哪些節點匹配並一次調整一個字元。
在 toolz。dev 上,流程很短。貼上 JSON 文檔,或載入大多數 JSONPath 教學使用的範例書店,鍵入表達式並進行評估。該工具將每個匹配值與運行計數一起列出,您可以在三個視圖之間切換輸出。值僅作為 JSON 數組為您提供結果。路徑為您提供每個匹配的標準化位置,這是發現您實際需要的表達式的最快方法。條目將兩者放在一起,以便您可以並排看到路徑和值。
與真實數據進行測試而不是在頭腦中推理的原因是因為來自野外的 JSON 比示例更混亂。字段有時是一個對象,有時是一個數組。您期望的密鑰在一半的記錄中遺失。數字以字串形式到達。根據實際有效負載運行表達式會立即而不是在部署時出現這些驚喜。
如何從數組中選擇項目?
陣列是大多數 JSONPath 工作發生的地方,有四種方法可以解決它們。
單一索引選擇一個元素。 $.store.book[0] 傳回第一本書,JSONPath 與大多數語言一樣,從零開始計數。負索引從最後開始計數,所以 $.store.book[-1] 退回最後一本書,無需您知道有多少本書。當您想要日誌中的最新項目或提要中的最新條目時,負片形式確實很有用。
通配符選擇每個元素。 $.store.book[*] 返回所有四本書,並且 $.store.book[*].author 傳回每個作者的作者,為您提供乾淨的作者數組。通配符也適用於物件,其中 $.store.* 傳回儲存物件的每個值,無論鍵如何。
聯盟選擇一個特定的集合。 $.store.book[0,2] 傳回第一本書和第三本書,相同的逗號語法適用於名稱,因此 $['store']['bicycle'] 括號引用的鍵可讓您對包含點形式無法包含的空格或標點符號的鍵進行尋址。
切片選擇一個範圍,借用 Python's start:end:step 形式。 $.store.book[:2] 取前兩個, $.store.book[1:3] 採用中間範圍,不包括最終索引, $.store.book[::2] 每兩個元素取一次,並且 $.store.book[::-1] 反轉數組。切片是語法中最不為人所知的部分,也是擁有它後保存最多打字的部分。
雙點有什麼作用?
雙點是遞歸下降,正是這個功能讓 JSONPath 感覺像是一種搜尋而不是一條路徑。 $..author 發現每一個 author 鍵入文件中的任何位置,無論嵌套有多深,並且 $..* 傳回每個層級的每個值。當您不知道文件的確切形狀時,或當同一欄位出現在多個深度時,遞歸下降會在一個表達式中找到所有這些內容。
考慮樣本書店。 $..price 傳回五個值,即四本書價格和自行車價格,因為它下降到每個物件並收集每個物件 price 它發現。一個平原 $.store.book[*].price 只傳回四本書的價格,因為它走的是固定的路線。這兩個表達式之間的差異是在已知地點要價與在任何地方要價之間的差異。
遞歸下降的力量足以構成危險,因為它可以比您所說的更匹配。這正是測試人員在這裡重要的原因。跑步 $..name 針對不熟悉的有效負載,您可能會發現它與您不知道共享金鑰的使用者名稱、產品名稱和檔案名稱相符。查看輸出中的路徑會告訴您是否在依賴表達式之前縮小表達式。
過濾表達式如何運作?
過濾器僅保留條件為真且已寫入的元素 [?(...)] 與 @ 代表當前元素。 $.store.book[?(@.price < 10)] 退回比十便宜的書。在過濾器內部,您可以與運算子將欄位與文字進行比較 ==, !=, <, <=, >, 和 >=(1) 測試場的存在,並將條件與 結合 && 和 ||.
一些具體的例子使形狀變得清晰:
$.store.book[?(@.category == "fiction")]選擇小說標題。$.store.book[?(@.price < 10 && @.category == "fiction")]縮小到廉價小說的範圍。$.store.book[?(@.isbn)]僅選擇具有 ISBN 的書籍,使用存在性而不是比較。$.vals[?(@ > 2)]過濾一個簡單的數字數組,其中@它本身指的是元素本身。
最常見的過濾器錯誤是類型不匹配。在 JSON 中, "12" 和 12 是不同的值,因此將數字欄位與引用的數字進行比較,或將字串欄位與裸數字進行比較的過濾器不會默默地匹配任何內容。當過濾器讓您感到驚訝時,首先要檢查的是欄位和文字是否為相同類型。根據真實資料測試表達式,您可以在其中看到實際值,這是如何在幾秒鐘內而不是在部署失敗後捕獲它。
JSONPath 與 JSON Pointer 與 JSON diff
這三種工具都觸及JSON結構,但它們回答不同的問題,選擇錯誤會浪費時間。以下是他們的比較方式:
| 方法 | 答案 | 比賽 | 最好 |
|---|---|---|---|
| JSON 路徑 | 哪些節點滿足此查詢? | 零、一或多 | 提取字段、過濾數組、探索未知形狀 |
| JSON 指針 (RFC 6901) | 這個確切位置是什麼? | 總是一 | 參考單一固定字段,如 JSON Schema 所示 $ref |
| JSON 差異 | 兩個文件之間發生了什麼變化? | 一組變化 | 比較相同數據的兩個版本 |
JSON 指針,定義於 RFC 6901,用斜線分隔的路徑尋址一個精確的地方,例如 /store/book/0/title,它從不使用通配符或過濾器。當您需要明確命名單一欄位時,請聯絡它。當單一表達式應選擇一組欄位時,請聯絡 JSONPath。當您真正的問題是兩個有效負載之間的差異而不是查詢選擇的內容時,a JSON 差異 是正確的工具。知道你真正需要三個中的哪一個就是一半的戰鬥。
為什麼我的表達式沒有回傳結果?
空的結果幾乎總是來自少數原因之一,測試人員可以讓您快速排除它們。
第一個是結構不匹配。你寫了 $.data.items.name 當 items 是一個數組,所以你需要 $.data.items[*].name 有通配符。點形式進入一個對象,數組不是具有 a 的對象 name 關鍵,所以路徑死胡同。將輸出視圖切換到路徑並一次步進一個段的表達式可以準確地顯示它停止匹配的位置。
第二個是拼字或大小寫錯誤。 JSON 鍵區分大小寫,因此 $.userId 不會匹配a userID 欄位、尾隨空格或鍵名中的拼字錯誤不會產生相同的靜音內容。因為測試人員會向您顯示表達式旁邊的文檔,因此這些內容很快就會被發現。
第三個,如上所述,是過濾器類型不匹配,其中數字比較與字串值或相反值進行。第四個假設每個元素都存在一個鍵,而該鍵僅存在於某些元素上。遞歸下降和存在過濾器是通常的補救措施。在每種情況下,修復都來自觀察表達式觸及哪些節點,這正是測試器的用途。
如果您像我一樣跨堆疊構建,在 Laravel API、React 前端和偶爾的 shell 腳本之間移動,JSONPath 將出現在這三者中,並且基於瀏覽器的測試器永遠不會上傳您的數據,這是我的工具保持最接近。我寫過這樣的實用程式如何適合更廣泛的套件 web 開發人員工具包並且將這種工作保留在客戶端的情況是存在的 線上工具中的資料隱私 指南。
這與我的 JSON 工作流程的其餘部分有何契合?
JSONPath 測試儀很少是唯一開啟的工具。當我正在查詢的 JSON 迷你化或縮排不一致時,我會將其運行到 json 格式化程式 首先,這樣我就可以在編寫表達式時讀取結構。格式化程式和測試器一起說明我如何從不可讀的 API 回應轉到工作查詢。
一旦我知道我關心哪些字段,下一步通常是重塑它們。如果需要將選定的值輸入電子表格或環境文件中, JSON 平坦器 將嵌套結構轉換為點符號鍵,其路徑語法與 JSONPath 足夠接近,以至於兩者相互強化。如果我在 TypeScript 中為資料建立一個類型,則 json 到打字稿 轉換器產生接口,如果我需要驗證形狀而不僅僅是讀取它,則 JSON 模式產生器 產生一個我可以添加約束的架構。 JSONPath 是探索步驟;這些工具就是我用我發現的東西來做的。
隱私點值得重複,因為 JSONPath 經常針對敏感資料進行工作。 API 回應攜帶令牌、使用者記錄和內部 ID,將它們貼上到伺服器端工具中意味著信任其他人's 日誌。因為 toolz。dev 測試儀完全在您的瀏覽器中解析和評估,這些都不會離開您的機器,並且該工具會繼續斷開網路。這就是您可以在暫存有效負載上使用的工具和可以在真實負載上使用的工具之間的差異。
常見問題
JSONPath 有何用途?
JSONPath 用於使用單一表達式選擇和提取 JSON 文件的部分內容。它是 API 測試工具、Kubernetes 輸出格式、AWS 步驟功能等雲端服務以及許多低程式碼平台中的查詢語言,只要有人需要從 JSON 有效負載中提取欄位或過濾數組而無需編寫程式程式碼。
如何選擇 JSONPath 中數組的每個元素?
使用通配符,所以 $.items[*] 傳回項目數組的每個元素 $.items[*].id 傳回每個元素的 id。您也可以按索引選擇一個元素 $.items[0],最後一個具有負索引的元素 $.items[-1]一個帶有聯合的集合 $.items[0,2]或具有類似切片的範圍 $.items[1:3].
雙點在 JSONPath 中意味著什麼?
雙點是遞歸下降,可以在任何深度進行搜尋。 $..author 在文件中的任何位置找到每個作者的密鑰,無論嵌套有多深,並且 $..* 傳回每個層級的每個值。這是從您事先不知道其確切結構的文件中提取欄位的最快方法。
過濾器表達式在 JSONPath 中如何運作?
一個過濾器 [?(...)] 僅保留條件為真的元素 @ 參考當前元素。例如 $.book[?(@.price < 10)] 退貨書比十本便宜,您可以將條件與 && 和 ||,例如 [?(@.price < 10 && @.category == "fiction")]。 您也可以測試欄位'的存在 [?(@.isbn)].
為什麼我的 JSONPath 表達式不傳回任何內容?
兩個最常見的原因是結構不匹配和類型不匹配。檢查每個鍵是否存在並用確切的外殼拼寫,並且您使用通配符,其中資料是數組而不是物件。在過濾器中,請記住 "12" 12 是不同的值,因此將字串欄位與引用值進行比較,將數字欄位與裸數進行比較。
JSONPath 和 JSON Pointer 有什麼不同?
JSON 指標尋址一個精確位置,例如/store/book/0/title,並且始終傳回單一值。 JSONPath 是一種查詢語言,其中單一表達式可以透過通配符、遞歸下降和過濾器同時匹配多個節點。使用指標引用一個固定字段,使用 JSONPath 選擇一組字段或過濾集合。
我可以看到每場比賽的路徑,而不僅僅是價值嗎?
是的。將輸出模式切換到路徑以獲得每個匹配的標準化位置,或將條目獲得路徑和值在一起。查看真實路徑是細化表達式的最快方法,直到它準確地選擇您想要的節點,這對於遞歸下降特別有幫助。
我使用測試儀時是否上傳了我的 JSON?
不。文件已解析,表達式將在使用 JavaScript 的瀏覽器中進行評估,因此不會傳輸、記錄或儲存任何內容。您可以在執行查詢時查看網路選項卡或與網路斷開連接來確認它,因為一旦頁面載入,測試人員就會繼續離線工作。
免費嘗試您自己的數據 JSONPath 測試儀. 它完全在瀏覽器中評估通配符、遞歸下降、切片、並集和過濾表達式,不上傳任何內容。



