ToolHub
View All Posts

คู่มือ JSONPath: วิธีค้นหาข้อมูล JSON

JSON ได้กลายเป็นภาษาสากลของเว็บ API ส่งคืน JSON ไฟล์กำหนดค่าใช้ JSON ฐานข้อมูลจัดเก็บเอกสาร JSON แต่เมื่อโครงสร้าง JSON มีขนาดใหญ่ขึ้นและซ้อนกันลึกขึ้น การค้นหาค่าเฉพาะจึงยากขึ้นเรื่อยๆ นี่คือจุดที่ JSONPath เข้ามามีบทบาท JSONPath เป็นภาษาคิวรีที่ช่วยให้คุณใช้นิพจน์เส้นทางที่กระชับเพื่อนำทางและดึงข้อมูลจากเอกสาร JSON เช่นเดียวกับที่ XPath ทำกับ XML คู่มือนี้ครอบคลุมทุกอย่างตั้งแต่ไวยากรณ์พื้นฐานไปจนถึงการกรองขั้นสูง พร้อมตัวอย่างที่ใช้งานได้จริงที่คุณสามารถนำไปใช้ได้ทันที

JSONPath คืออะไร?

JSONPath เป็นภาษาคิวรี JSON ที่เสนอครั้งแรกโดย Stefan Goessner ในปี 2007 มีไวยากรณ์ที่กะทัดรัดสำหรับการเลือกโหนดจากเอกสาร JSON คล้ายกับ CSS selector ที่ระบุตำแหน่งองค์ประกอบ HTML หรือ XPath expression ที่ระบุตำแหน่งโหนด XML คุณไม่จำเป็นต้องเขียนลูปและตรรกะเงื่อนไขเพื่อสำรวจโครงสร้าง JSON เพียงเขียนนิพจน์ที่อธิบายเส้นทางไปยังข้อมูลที่ต้องการ

นิพจน์ JSONPath เริ่มต้นจากโหนดรากของเอกสาร JSON และนำทางผ่านออบเจ็กต์และอาร์เรย์ไปยังค่าที่ต้องการ ภาษานี้รองรับไวด์การ์ด การสืบทอดแบบเรียกซ้ำ การแบ่งส่วนอาร์เรย์ และนิพจน์ตัวกรอง ซึ่งเพียงพอสำหรับความต้องการในการดึงข้อมูลส่วนใหญ่

เอกสาร JSON ตัวอย่าง

ในคู่มือนี้ เราจะใช้เอกสาร JSON ต่อไปนี้เป็นตัวอย่างการทำงาน นี่คือตัวอย่างคลาสสิกจากข้อเสนอ JSONPath ดั้งเดิม พร้อมข้อมูลเพิ่มเติม:

{
  "store": {
    "book": [
      {
        "category": "reference",
        "author": "Nigel Rees",
        "title": "Sayings of the Century",
        "price": 8.95
      },
      {
        "category": "fiction",
        "author": "Evelyn Waugh",
        "title": "Sword of Honour",
        "price": 12.99
      },
      {
        "category": "fiction",
        "author": "Herman Melville",
        "title": "Moby Dick",
        "isbn": "0-553-21311-3",
        "price": 8.99
      },
      {
        "category": "fiction",
        "author": "J.R.R. Tolkien",
        "title": "The Lord of the Rings",
        "isbn": "0-395-19395-8",
        "price": 22.99
      }
    ],
    "bicycle": {
      "color": "red",
      "price": 19.95
    }
  }
}

ข้อมูลอ้างอิงไวยากรณ์ JSONPath

JSONPath ใช้ชุดตัวดำเนินการขนาดเล็กที่รวมกันเพื่อสร้างคิวรีที่มีประสิทธิภาพ นี่คือข้อมูลอ้างอิงไวยากรณ์ที่สมบูรณ์:

ตัวดำเนินการคำอธิบายตัวอย่าง
$โหนดรากของเอกสาร$
.ตัวดำเนินการลูก (เข้าถึงคุณสมบัติออบเจ็กต์)$.store
[]ดัชนีอาร์เรย์หรือตัวดำเนินการลูก$.store.book[0]
[*]ไวด์การ์ดสำหรับองค์ประกอบอาร์เรย์ทั้งหมด$.store.book[*]
..การสืบทอดแบบเรียกซ้ำ (ค้นหาทุกระดับ)$..author
.keyคุณสมบัติออบเจ็กต์ที่มีชื่อ$.store.bicycle
['key']สัญกรณ์วงเล็บสำหรับการเข้าถึงคุณสมบัติ$['store']['book']
[start:end]การแบ่งส่วนอาร์เรย์ (ไม่รวมดัชนีสิ้นสุด)$.store.book[0:2]
[?()]นิพจน์ตัวกรอง< 10)]
()นิพจน์สคริปต์ (ขึ้นอยู่กับการใช้งาน)$.store.book[(@.length-1)]

นิพจน์ JSONPath พื้นฐาน

การเข้าถึงโหนดรากและโหนดลูกโดยตรง

เครื่องหมายดอลลาร์ $ แสดงถึงโหนดรากของเอกสาร JSON จากนั้นคุณใช้สัญกรณ์จุดเพื่อเข้าถึงคุณสมบัติของออบเจ็กต์ และใช้สัญกรณ์วงเล็บเพื่อเข้าถึงดัชนีของอาร์เรย์

นิพจน์ผลลัพธ์
$เอกสาร JSON ทั้งหมด
$.storeออบเจ็กต์ store (ประกอบด้วยอาร์เรย์ book และออบเจ็กต์ bicycle)
$.store.bicycle{"color": "red", "price": 19.95}
$.store.bicycle.color"red"
$.store.bookอาร์เรย์ book ทั้งหมด
$.store.book[0]ออบเจ็กต์หนังสือเล่มแรก
$.store.book[0].title"Sayings of the Century"
$.store.book[3].author"J.R.R. Tolkien"

สัญกรณ์วงเล็บ

สัญกรณ์วงเล็บเป็นทางเลือกแทนสัญกรณ์จุด มีประโยชน์เมื่อชื่อคุณสมบัติมีอักขระพิเศษ ช่องว่าง หรือขึ้นต้นด้วยตัวเลข:

$.store['book'][0]['title']
$['store']['bicycle']['color']

สัญกรณ์วงเล็บและสัญกรณ์จุดสามารถใช้แทนกันได้สำหรับคุณสมบัติของออบเจ็กต์ อย่างไรก็ตาม เมื่อชื่อคุณสมบัติเป็นแบบไดนามิกหรือมีอักขระที่ไม่ถูกต้องในสัญกรณ์จุด ต้องใช้สัญกรณ์วงเล็บ

ตัวดำเนินการไวด์การ์ด

ตัวดำเนินการไวด์การ์ด * จับคู่กับองค์ประกอบทั้งหมดในอาร์เรย์หรือคุณสมบัติทั้งหมดในออบเจ็กต์ มีประโยชน์อย่างมากสำหรับการดึงค่าทั้งหมดในระดับหนึ่งโดยไม่ต้องรู้คีย์หรือดัชนีที่เฉพาะเจาะจง

นิพจน์ผลลัพธ์
$.store.*ค่าทั้งหมดในออบเจ็กต์ store (อาร์เรย์ book และออบเจ็กต์ bicycle)
$.store.book[*]หนังสือทั้งหมดในอาร์เรย์ (ออบเจ็กต์ book ทั้งสี่)
$.store.book[*].authorชื่อผู้แต่งทั้งหมด: ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]
$.store.*.priceราคาของ bicycle และอาร์เรย์ book (ไม่ใช่ราคาของหนังสือแต่ละเล่ม)

การสืบทอดแบบเรียกซ้ำ: ตัวดำเนินการจุดคู่

ตัวดำเนินการจุดคู่ .. เป็นหนึ่งในฟีเจอร์ที่ทรงพลังที่สุดของ JSONPath มันค้นหาคีย์ที่ระบุในทุกระดับของโครงสร้าง JSON ไม่ใช่แค่โหนดลูกโดยตรง ลองนึกภาพว่าเป็นการค้นหาเชิงลึกทั่วทั้งเอกสาร

นิพจน์ผลลัพธ์
$..authorค่า author ในทุกตำแหน่งของเอกสาร
$..priceค่า price ทั้งหมด: [8.95, 12.99, 8.99, 22.99, 19.95]
$..book[2]หนังสือเล่มที่สาม ค้นหาแบบเรียกซ้ำ
$..categoryค่า category ทั้งหมด: ["reference", "fiction", "fiction", "fiction"]

ตัวดำเนินการสืบทอดแบบเรียกซ้ำมีประโยชน์อย่างยิ่งเมื่อคุณไม่ทราบเส้นทางที่แน่นอนของข้อมูลที่ต้องการ หรือเมื่อคีย์เดียวกันปรากฏในหลายระดับที่ซ้อนกัน ตัวอย่างเช่น หากการตอบสนอง API มีฟิลด์ id ในระดับที่ซ้อนกันต่างๆ $..id จะรวบรวม id ทั้งหมด

การแบ่งส่วนอาร์เรย์

การแบ่งส่วนอาร์เรย์ช่วยให้คุณเลือกช่วงขององค์ประกอบจากอาร์เรย์ ไวยากรณ์ [start:end] เลือกองค์ประกอบจากดัชนีเริ่มต้นจนถึง (แต่ไม่รวม) ดัชนีสิ้นสุด รองรับดัชนีบวกและลบ

นิพจน์ผลลัพธ์
$.store.book[0:2]หนังสือสองเล่มแรก (ดัชนี 0 และ 1)
$.store.book[1:3]หนังสือเล่มที่สองและสาม (ดัชนี 1 และ 2)
$.store.book[-1]หนังสือเล่มสุดท้าย (The Lord of the Rings)
$.store.book[-2:]หนังสือสองเล่มสุดท้าย
$.store.book[:2]หนังสือสองเล่มแรก (เหมือน [0:2])
$.store.book[2:]หนังสือเล่มที่สามและหลังจากนั้น

โปรดทราบว่าพฤติกรรมการแบ่งส่วนอาจแตกต่างกันเล็กน้อยระหว่างการใช้งาน JSONPath ที่แตกต่างกัน ไวยากรณ์ข้างต้นปฏิบัติตามแบบแผนที่ใช้โดยไลบรารียอดนิยมส่วนใหญ่และมาตรฐาน IETF RFC 9535

นิพจน์ตัวกรอง

นิพจน์ตัวกรองคือจุดที่ JSONPath มีประสิทธิภาพอย่างแท้จริง มันช่วยให้คุณเลือกองค์ประกอบตามเงื่อนไขแทนที่จะเป็นตำแหน่ง ไวยากรณ์ตัวกรองใช้ [?(condition)] โดยที่เงื่อนไขถูกประเมินสำหรับแต่ละองค์ประกอบ

ตัวดำเนินการเปรียบเทียบ

JSONPath รองรับตัวดำเนินการเปรียบเทียบต่อไปนี้ในนิพจน์ตัวกรอง:

ตัวดำเนินการความหมายตัวอย่าง
==เท่ากับ[?(@.category == "fiction")]
!=ไม่เท่ากับ[?(@.category != "fiction")]
<น้อยกว่า< 10)]
<=น้อยกว่าหรือเท่ากับ<= 8.99)]
>มากกว่า[?(@.price > 15)]
>=มากกว่าหรือเท่ากับ[?(@.price >= 12.99)]
=~การจับคู่ regex (บางการใช้งาน)[?(@.author =~ /Tolkien/i)]

ตัวอย่างตัวกรองที่ใช้งานได้จริง

ใช้เอกสารตัวอย่างของเรา นี่คือนิพจน์ตัวกรองที่ใช้งานได้จริงและผลลัพธ์:

Find all books cheaper than $10:

< 10)]

ส่งคืนหนังสือ "Sayings of the Century" ($8.95) และ "Moby Dick" ($8.99)

Find all fiction books:

$.store.book[?(@.category == "fiction")]

ส่งคืนหนังสือสามเล่ม: "Sword of Honour", "Moby Dick" และ "The Lord of the Rings"

Find books with an ISBN:

$.store.book[?(@.isbn)]

ส่งคืนหนังสือที่มีคุณสมบัติ isbn: "Moby Dick" และ "The Lord of the Rings" เนื่องจากตัวกรองตรวจสอบว่ามีคุณสมบัติอยู่หรือไม่

Find the most expensive book:

$.store.book[?(@.price > 20)]

ส่งคืน "The Lord of the Rings" ($22.99)

ตัวดำเนินการตรรกะในตัวกรอง

คุณสามารถใช้ตัวดำเนินการตรรกะเพื่อรวมเงื่อนไข:

< 10 && @.category == "fiction")]
$.store.book[?(@.price > 15 || @.category == "reference")]

นิพจน์แรกค้นหาหนังสือนิยายที่ต่ำกว่า $10 (เฉพาะ "Moby Dick") นิพจน์ที่สองค้นหาหนังสือที่มากกว่า $15 หรืออยู่ในหมวดหมู่อ้างอิง (ส่งคืน "Sayings of the Century" และ "The Lord of the Rings")

JSONPath กับ XPath

JSONPath ถูกสร้างแบบจำลองตาม XPath อย่างชัดเจน และทั้งสองภาษามีความคล้ายคลึงกันในเชิงแนวคิดหลายประการ หากคุณคุ้นเคยกับการประมวลผล XML การเข้าใจความสัมพันธ์นี้จะเป็นประโยชน์

ฟังก์ชันJSONPathXPath
สัญลักษณ์ราก$/
การเข้าถึงลูก.key หรือ ['key']/element
ดัชนีอาร์เรย์[0][1] (เริ่มจาก 1)
ไวด์การ์ด**
การสืบทอดแบบเรียกซ้ำ..//
ตัวกรอง[?(condition)][condition]
แอตทริบิวต์ไม่สามารถใช้ได้ (JSON ไม่มีแอตทริบิวต์)@attr
โหนดปัจจุบัน@ (ในตัวกรอง). หรือ current()
โหนดแม่ไม่รองรับ..
แกนไม่รองรับ13 แกน (ancestor, following ฯลฯ)
โมเดลข้อมูลออบเจ็กต์และอาร์เรย์องค์ประกอบ แอตทริบิวต์ โหนดข้อความ

ความแตกต่างที่สำคัญคือ XPath ทำงานบนโมเดลต้นไม้ที่หลากหลายซึ่งมีองค์ประกอบ แอตทริบิวต์ โหนดข้อความ เนมสเปซ และคำสั่งประมวลผล JSONPath ทำงานบนโมเดลที่เรียบง่ายกว่าของออบเจ็กต์ (การแมปคีย์-ค่า) และอาร์เรย์ (รายการเรียงลำดับ) ความเรียบง่ายนี้ทำให้ JSONPath เรียนรู้ได้ง่ายขึ้น แต่มีความสามารถในการแสดงออกน้อยกว่า XPath สำหรับคิวรีที่ซับซ้อน

การใช้งาน JSONPath ในทางปฏิบัติ

การทดสอบ API

JSONPath เป็นสิ่งที่ขาดไม่ได้สำหรับการทดสอบ API เมื่อคุณส่งคำขอไปยัง API และได้รับการตอบสนอง JSON ขนาดใหญ่ JSONPath ช่วยให้คุณยืนยันค่าเฉพาะโดยไม่ต้องนำทางโครงสร้างทั้งหมดด้วยตนเอง เครื่องมือทดสอบ API ส่วนใหญ่รองรับ JSONPath โดยตรง

ตัวอย่างเช่น ในการทดสอบคุณอาจตรวจสอบว่าราคาของหนังสือเล่มแรกต่ำกว่า $10:

// Using a JSONPath assertion in testing
response.jsonPath().get("store.book[0].price").should(equals(8.95));

// Find all books by a specific author
response.jsonPath().get("store.book[?(@.author == 'Herman Melville')].title");
// Returns: ["Moby Dick"]

การแปลงข้อมูล

เมื่อรวมระบบที่ใช้รูปแบบข้อมูลที่แตกต่างกัน JSONPath ช่วยดึงและแปลงฟิลด์เฉพาะ คุณสามารถดึงค่าจากโครงสร้าง JSON หนึ่งและแมปไปยังอีกโครงสร้างหนึ่งโดยไม่ต้องเขียนโค้ดการสำรวจที่ซับซ้อน

การจัดการการกำหนดค่า

ไฟล์กำหนดค่าที่ซับซ้อนมักมี JSON ที่ซ้อนกันลึก JSONPath ช่วยให้คุณคิวรีค่ากำหนดค่าเฉพาะโดยไม่ต้องโหลดและแยกวิเคราะห์โครงสร้างทั้งหมด เครื่องมือเช่น jq ใช้ไวยากรณ์คล้าย JSONPath เพื่อประมวลผล JSON ในไปป์ไลน์บรรทัดคำสั่ง

การตรวจสอบและการแจ้งเตือน

ในระบบการตรวจสอบ observability คิวรี JSONPath สามารถดึงเมตริกจากบันทึกและการตอบสนอง API ในรูปแบบ JSON คุณสามารถตั้งค่าการแจ้งเตือนที่ทริกเกอร์เมื่อคิวรี JSONPath ส่งคืนค่าที่เกินเกณฑ์

การใช้งาน JSONPath

JSONPath มีให้ใช้งานในเกือบทุกภาษาโปรแกรม นี่คือไลบรารียอดนิยม:

ภาษาไลบรารีการติดตั้ง
JavaScriptjsonpath-plusnpm install jsonpath-plus
Pythonjsonpath-ngpip install jsonpath-ng
JavaJsonPath (Jayway)Maven: com.jayway.jsonpath
C#Json.NET (Newtonsoft)NuGet: Newtonsoft.Json
Gogjsongo get github.com/tidwall/gjson
PHPjsonpathcomposer require softcreatr/jsonpath
Rubyjsonpathgem install jsonpath

ตัวอย่าง JavaScript

< 10)]',
  json: data
});
// Returns books with price < 10

Python Example

from jsonpath_ng import parse

data = { /* our sample JSON */ }

# Find all authors
author_expr = parse('$..author')
authors = [match.value for match in author_expr.find(data)]
# ["Nigel Rees", "Evelyn Waugh", "Herman Melville", "J.R.R. Tolkien"]

# Find cheap books
cheap_expr = parse('$.store.book[?(@.price < 10)]')
cheap_books = [match.value for match in cheap_expr.find(data)]

Common Pitfalls and Tips

เคล็ดลับ: เมื่อทำงานกับนิพจน์ JSONPath ที่ซับซ้อน ให้สร้างทีละขั้นตอน เริ่มจากเส้นทางง่ายๆ เช่น $.store ตรวจสอบว่าใช้งานได้ จากนั้นค่อยๆ ขยาย: $.store.book จากนั้น $.store.book[*] จากนั้น $.store.book[*].price และสุดท้ายเพิ่มตัวกรอง วิธีนี้ทำให้การดีบักง่ายขึ้น

ข้อผิดพลาดและเคล็ดลับที่พบบ่อย

ในปี 2024 IETF ได้เผยแพร่ RFC 9535 ซึ่งกำหนดมาตรฐาน JSONPath อย่างเป็นทางการ ข้อกำหนดนี้แก้ไขความคลุมเครือและความไม่สอดคล้องกันหลายประการที่มีอยู่ระหว่างการใช้งานต่างๆ ประเด็นสำคัญของมาตรฐานรวมถึง:

หากคุณกำลังเริ่มโปรเจกต์ใหม่ ให้เลือกไลบรารีที่ใช้งาน RFC 9535 เพื่อความเข้ากันได้สูงสุดและพฤติกรรมที่คาดการณ์ได้

ต้องการคิวรีข้อมูล JSON อย่างรวดเร็ว? ลองใช้ตัวทดสอบ JSONPath ออนไลน์ฟรีของเรา ประเมินนิพจน์กับเอกสาร JSON ของคุณแบบเรียลไทม์

ลองใช้ตัวค้นหา JSONPath

มาตรฐาน IETF: RFC 9535

ตัวอย่าง Python

JSONPath เป็นภาษาคิวรี JSON คล้ายกับ XPath สำหรับ XML ใช้นิพจน์เส้นทางเพื่อนำทางและดึงค่าเฉพาะจากเอกสาร JSON นิพจน์ JSONPath เช่น $.store.book[0].title ช่วยให้คุณระบุตำแหน่งข้อมูลในโครงสร้าง JSON ที่ซ้อนกันซับซ้อนได้อย่างแม่นยำ โดยไม่ต้องเขียนโค้ดแยกวิเคราะห์เอง

JSONPath คืออะไร?

JSONPath ถูกออกแบบมาสำหรับโครงสร้างออบเจ็กต์และอาร์เรย์ของ JSON ในขณะที่ XPath ถูกออกแบบมาสำหรับต้นไม้องค์ประกอบและแอตทริบิวต์ของ XML JSONPath ใช้ $ เป็นโหนดราก สัญกรณ์จุดเพื่อเข้าถึงออบเจ็กต์ และสัญกรณ์วงเล็บเพื่อเข้าถึงอาร์เรย์ XPath ใช้ / สำหรับการแยกเส้นทาง และ @ เพื่อเข้าถึงแอตทริบิวต์ JSONPath เรียบง่ายกว่าแต่มีฟีเจอร์น้อยกว่า XPath

JSONPath แตกต่างจาก XPath อย่างไร?

จุดคู่ (..) ใน JSONPath เป็นตัวดำเนินการสืบทอดแบบเรียกซ้ำ มันค้นหาคีย์ที่ระบุในทุกระดับของโครงสร้าง JSON ไม่ใช่แค่โหนดลูกโดยตรง ตัวอย่างเช่น $..author ค้นหาคีย์ author ทั้งหมดในทุกตำแหน่งทั่วทั้งเอกสาร ไม่ว่ามันจะซ้อนกันลึกเพียงใด

จุดคู่ (..) ใน JSONPath หมายถึงอะไร?

<, ><=, >< 10)] ค้นหาหนังสือทั้งหมดที่ต่ำกว่า $10

JSONPath สามารถกรองข้อมูลตามเงื่อนไขได้หรือไม่?

JSONPath ถูกเสนอครั้งแรกโดย Stefan Goessner ในปี 2007 โดยไม่มีข้อกำหนดอย่างเป็นทางการ ทำให้เกิดความแตกต่างระหว่างการใช้งานต่างๆ ในปี 2024 IETF ได้เผยแพร่ RFC 9535 ซึ่งกำหนดมาตรฐาน JSONPath อย่างเป็นทางการ การใช้งานสมัยใหม่กำลังบรรจบกันสู่มาตรฐานนี้ แต่ไลบรารีเก่าบางตัวอาจยังมีความแตกต่างทางไวยากรณ์เล็กน้อย