
JSONPath、jq 與 JavaScript 路徑有何不同?從 RFC 9535 看懂查詢差異
想從 JSON 取出第一筆商品的名稱,有的工具使用 $.items[0].name,有的接受 .items[0].name,有的函式庫則使用 ["items",0,"name"]。這些寫法看起來很像,直接複製到另一個工具卻可能無法執行,或得到不同結果。
本文以 RFC 9535 定義的 JSONPath 為主軸,比較 jq 篩選器、JavaScript 屬性存取與 lodash 路徑。關鍵是把它們視為由不同引擎解讀的不同語言,而不是可以任意互換的「JSON 地址」。
日文原文發布: 2026-06-09
JSONPath 用來選取 JSON 文件中的節點
JSONPath 是從 JSON 值中選取節點的查詢語法。以下列資料為例,$.items[0].name 會選取第一筆商品的名稱。價格沿用日本原文,單位為日圓。
{
"items": [
{ "name": "USB-C 傳輸線", "price": 1200 },
{ "name": "充電器", "price": 2980 }
]
}
$ 代表根節點,.items 選取物件的成員,[0] 選取陣列中的第一個元素,.name 再選取其中的名稱。這次選到的值是 "USB-C 傳輸線"。它看似檔案路徑,實際上卻是在查詢 JSON 的樹狀結構。
RFC 9535 標準化了哪些行為?
JSONPath 過去在不同實作之間存在不少差異。2024 年 2 月發布的 RFC 9535 定義了共同的語法與選取規則,但較早的實作和額外擴充仍須與標準分開看待。
表格若超出畫面寬度,可左右捲動。
| 寫法 | 意義 | 範例 |
|---|---|---|
$ | 根節點 | $ |
.name | 依名稱選取子節點 | $.items |
['name'] | 用引號指定成員名稱 | $['user.name'] |
[0] | 陣列索引 | $.items[0] |
[*] | 選取所有子節點 | $.items[*].name |
..name | 搜尋後代節點 | $..price |
[?expr] | 依條件篩選 | $.items[?@.price < 2000] |
標準不只列出符號,也定義結果為「節點清單」(nodelist)、篩選條件內的 @ 代表目前節點,以及萬用字元與陣列切片等操作的意義。工具標示支援 JSONPath,不代表它已實作標準的全部功能。
$ 與 @ 指向不同的節點
$ 一律指向整份文件的根節點;篩選條件中的 @ 則指向目前正在檢查的節點。
$.items[?@.price < 2000].name
這個查詢逐一檢查 items 裡的商品。@.price 是目前這筆商品的價格,因此會選到 "USB-C 傳輸線"。若改成 $.price,就會尋找根節點底下的 price;上面的範例並沒有這個成員。
jq 的篩選器不是 JSONPath 查詢
jq 的 . 是原樣傳回輸入的 identity filter,.foo 則取出名為 foo 的成員。.items[0].name 雖然很像 JSONPath,仍屬於 jq 自己的語言。jq 還能轉換資料、計算、透過管線串接操作、建立陣列及產生多筆輸出。
表格若超出畫面寬度,可左右捲動。
| 目的 | JSONPath | jq |
|---|---|---|
| 第一筆商品的名稱 | $.items[0].name | .items[0].name |
| 所有商品名稱 | $.items[*].name | .items[].name |
| 價格低於 2,000 日圓的商品 | $.items[?@.price < 2000] | .items[] | select(.price < 2000) |
這張表以開頭範例的數值價格為前提。jq 對不同型別也定義了大小順序,所以 price 不存在或值為 null 時,也會符合 .price < 2000。若只比較數值,可使用 .items[] | select(.price | numbers) | select(.price < 2000) 先限定型別。JSONPath 與數值進行大小比較時,並不是同樣的行為。
jq 的 .items[].name 會逐筆輸出名稱。JSONPath 回傳節點清單,並非會移除重複項目的集合:對 ["a","b"] 使用 $[0,0],第一個節點會被選取兩次;把選到的值表示成陣列,就是 ["a","a"]。陣列的萬用字元選取會保留陣列順序,但 RFC 不保證物件萬用字元選取的成員順序。
JavaScript 屬性存取是可執行的運算式
obj.items[0].name 是 JavaScript 的屬性存取。它是程式執行時求值的運算式,與交給 JSONPath 引擎解讀的查詢字串不同。
{ "user.name": "小安", "user": { "name": "小文" } }
$.user.name選取巢狀物件中的名稱"小文"。$['user.name']選取名稱含有句點的單一成員,其值為"小安"。obj.user.name是 JavaScript 對巢狀屬性的存取。obj["user.name"]是 JavaScript 對名稱含句點之屬性的存取。
儲存路徑字串與執行程式碼是兩件事。不要把使用者輸入的任意路徑直接當成 JavaScript 執行;應解析明確支援的路徑語法,再依各個組成部分存取資料。
lodash 路徑也不是標準 JSONPath
_.get(object, path) 可接受 "a[0].b.c" 這類字串,或 ["a",0,"b","c"] 這類陣列。它會沿著屬性路徑取得值,但不會因此讓路徑字串具備 RFC 9535 的語意。
items[0].name 這類簡單寫法看似相近,JSONPath 的萬用字元、後代搜尋及篩選條件卻不能直接套用到 lodash。要區分含句點的完整鍵名與巢狀屬性,可明確使用路徑陣列:["user.name"] 與 ["user","name"] 是不同路徑。
跨工具使用時,留意這五個差異
- 根節點寫法:RFC 9535 的最外層查詢必須以
$開頭,篩選條件內則可使用@。jq 用.存取輸入,但不是每個 jq 篩選器都以句點開頭。 - 逐一處理陣列元素:JSONPath 使用
[*],jq 使用[]。 - 鍵名包含句點:若句點是名稱的一部分,必須將完整名稱放在引號中,例如
['user.name']。 - 成員不存在:JSONPath 不會選到任何節點,這與選到一個值為
null的節點不同。 - 篩選條件:JSONPath 的
[?@.x]檢查 x 是否存在;即使值為false或null也會選取。jq 的select(.x)會排除 false 與 null,卻會保留 0 與空字串。這也不同於 JavaScript 的真假值判定。
{ "x": null }
對這個輸入,$.missing 選到零個節點,$.x 選到一個值為 null 的節點。下表 JSONPath 欄位中的 [] 與 [null],是將選到的值表示成陣列;各 API 封裝節點清單的方式可能不同。
表格若超出畫面寬度,可左右捲動。
| 處理方式 | 不存在的 missing 成員 | 存在的 x 成員 |
|---|---|---|
| JSONPath | $.missing → [] | $.x → [null] |
| jq | .missing → null | .x → null |
| JavaScript | obj.missing → undefined | obj.x → null |
| lodash | _.get(obj, ["missing"], "預設值") → "預設值" | _.get(obj, ["x"], "預設值") → null |
JavaScript 若繼續存取 obj.missing.name,會拋出 TypeError;改用 obj.missing?.name 則得到 undefined。lodash 只在解析結果為 undefined 時使用預設值,不會將 null 換成預設值。
以 [{"x":false},{"x":null},{"x":0},{"x":""},{}] 為例,JSONPath 的 $[?@.x] 會選取前四個物件;jq 的 .[] | select(.x) 只會輸出 x 為 0 與空字串的兩個物件。無論是檢查 API 回應、分析紀錄或撰寫自動化測試,分享查詢時都應說明使用哪種語言與引擎,而不只稱它為「JSON 路徑」。
顯示位置的路徑,不一定是可執行的查詢
畫面上用 items[0].name 告訴讀者資料在哪裡,不一定需要完整的 JSONPath 語法。但用來擷取資料或執行測試的查詢,必須符合目標引擎的語法與支援範圍。
NanToo 的 JSONPath Finder 目前僅提供日文版。選取樹狀結構中的節點後,會並列顯示 JSONPath、JavaScript、Python、jq 與 lodash 五種存取形式,並提供個別複製按鈕。查詢輸入欄僅支援部分語法,並不是完整的 RFC 9535 驗證器。若要在該工具比較數值,可使用 $.items[?(@.price < 2000)].name;這個工具要求條件外加上小括號,雖然 RFC 允許省略。本文提到的存在篩選、重複選取 $[0,0]、陣列切片及複合條件,都不在該工具的支援範圍內。
排查路徑問題前,可先用台灣版的 JSON 格式化與驗證工具 確認輸入,再選擇支援所需查詢的引擎。JSON 格式是否有效,與 JSONPath 查詢如何執行,是不同的問題。
參考資料與來源
編輯說明
本文使用 AI 協助編輯,並於發布前由編輯確認。內容仍可能包含事實、解讀或時效上的錯誤;進行重要判斷前,請查閱所列的一手資料或官方文件。

