ToolHub
View All Posts

Hướng Dẫn Truy Vấn JSONPath: Cách Tìm Kiếm Dữ Liệu JSON

JSON đã trở thành ngôn ngữ chung của web. API trả về JSON, file cấu hình sử dụng JSON, cơ sở dữ liệu lưu trữ tài liệu JSON. Nhưng khi cấu trúc JSON trở nên lớn hơn và lồng sâu hơn, việc tìm giá trị cụ thể ngày càng khó khăn. Đây là lúc JSONPath xuất hiện. JSONPath là ngôn ngữ truy vấn cho phép bạn sử dụng biểu thức đường dẫn ngắn gọn để điều hướng và trích xuất dữ liệu từ tài liệu JSON, giống như XPath làm với XML. Hướng dẫn này bao gồm mọi thứ từ cú pháp cơ bản đến lọc nâng cao với các ví dụ thực tế bạn có thể áp dụng ngay.

JSONPath Là Gì?

JSONPath là ngôn ngữ truy vấn JSON, ban đầu được Stefan Goessner đề xuất năm 2007. Nó cung cấp cú pháp gọn để chọn nút từ tài liệu JSON, tương tự như CSS selector định vị phần tử HTML hoặc biểu thức XPath định vị nút XML. Thay vì viết vòng lặp và logic điều kiện để duyệt cấu trúc JSON, bạn chỉ cần viết một biểu thức mô tả đường dẫn đến dữ liệu mong muốn.

Biểu thức JSONPath bắt đầu từ nút gốc của tài liệu JSON và điều hướng qua các đối tượng và mảng đến giá trị mong muốn. Ngôn ngữ này hỗ trợ wildcard, recursive descent, array slicing và biểu thức lọc, đủ mạnh cho hầu hết nhu cầu trích xuất dữ liệu.

Tài Liệu JSON Mẫu

Trong hướng dẫn này, chúng tôi sẽ sử dụng tài liệu JSON sau làm ví dụ làm việc. Đây là ví dụ kinh điển từ đề xuất JSONPath gốc với dữ liệu bổ sung:

{
  "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
    }
  }
}

Tham Khảo Cú Pháp JSONPath

JSONPath sử dụng một bộ toán tử nhỏ kết hợp để tạo thành truy vấn mạnh mẽ. Đây là tham khảo cú pháp đầy đủ:

Toán TửMô TảVí Dụ
$Nút gốc của tài liệu$
.Toán tử con (truy cập thuộc tính đối tượng)$.store
[]Toán tử chỉ mục mảng hoặc con$.store.book[0]
[*]Wildcard cho tất cả phần tử mảng$.store.book[*]
..Recursive descent (tìm kiếm tất cả cấp)$..author
.keyThuộc tính đối tượng được đặt tên$.store.bicycle
['key']Ký hiệu dấu ngoặc cho truy cập thuộc tính$['store']['book']
[start:end]Array slicing (chỉ mục kết thúc không bao gồm)$.store.book[0:2]
[?()]Biểu thức lọc< 10)]
()Biểu thức script (phụ thuộc triển khai)$.store.book[(@.length-1)]

Biểu Thức JSONPath Cơ Bản

Truy Cập Nút Gốc và Con Trực Tiếp

Ký hiệu đô la $ đại diện cho nút gốc của tài liệu JSON. Từ đó, bạn sử dụng ký hiệu dấu chấm để truy cập thuộc tính đối tượng và ký hiệu dấu ngoặc để truy cập chỉ mục mảng.

Biểu ThứcKết Quả
$Toàn bộ tài liệu JSON
$.storeĐối tượng store (chứa mảng book và đối tượng bicycle)
$.store.bicycle{"color": "red", "price": 19.95}
$.store.bicycle.color"red"
$.store.bookToàn bộ mảng book
$.store.book[0]Đối tượng sách đầu tiên
$.store.book[0].title"Sayings of the Century"
$.store.book[3].author"J.R.R. Tolkien"

Ký Hiệu Dấu Ngoặc

Ký hiệu dấu ngoặc là thay thế cho ký hiệu dấu chấm khi tên thuộc tính chứa ký tự đặc biệt, khoảng trắng hoặc bắt đầu bằng số:

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

Ký hiệu dấu ngoặc và ký hiệu dấu chấm có thể hoán đổi cho thuộc tính đối tượng. Tuy nhiên, khi tên thuộc tính là động hoặc chứa ký tự không hợp lệ trong ký hiệu dấu chấm, phải sử dụng ký hiệu dấu ngoặc.

Toán Tử Wildcard

Toán tử wildcard * khớp với tất cả phần tử trong mảng hoặc tất cả thuộc tính trong đối tượng. Nó cực kỳ hữu ích để trích xuất tất cả giá trị ở một cấp mà không cần biết khóa hoặc chỉ mục cụ thể.

Toán TửÝ Nghĩa
$.store.*Tất cả giá trị trong đối tượng store (mảng book và đối tượng bicycle)
$.store.book[*]Tất cả phần tử trong mảng book
== !=Bằng, không bằng
@.price == 8.95< ><= >=

Recursive Descent: Toán Tử Dấu Chấm Đôi

Toán tử dấu chấm đôi .. là một trong những tính năng mạnh nhất của JSONPath. Nó tìm kiếm khóa được chỉ định ở mọi cấp của cây JSON, không chỉ con trực tiếp. Hãy nghĩ về nó như tìm kiếm sâu trên toàn bộ tài liệu.

Chức NăngJSONPath
So sánh số< 10
=~Khớp regex (phụ thuộc triển khai)
@.title =~ /Century/&& || !
Toán tử logic< 10 && @.category == 'fiction'

Toán tử recursive descent đặc biệt hữu ích khi bạn không biết đường dẫn chính xác đến dữ liệu mong muốn, hoặc khi cùng một khóa xuất hiện ở nhiều cấp lồng nhau. Ví dụ, nếu phản hồi API chứa trường id ở nhiều cấp lồng khác nhau, $..id sẽ thu thập tất cả id.

Array Slicing

Array slicing cho phép bạn chọn một phạm vi phần tử từ mảng. Cú pháp [start:end] chọn phần tử từ chỉ mục bắt đầu đến (nhưng không bao gồm) chỉ mục kết thúc. Hỗ trợ cả chỉ mục dương và âm.

XPathNgôn Ngữ
JavaScriptjsonpath-plus
npm install jsonpath-plusPython
jsonpath-ngpip install jsonpath-ng
JavaJayway JsonPath
implementation 'com.jayway.jsonpath:json-path'Go
github.com/PaesslerAG/jsonpathgo get github.com/PaesslerAG/jsonpath

Lưu ý rằng hành vi slicing có thể khác biệt nhẹ giữa các triển khai JSONPath. Cú pháp trên tuân theo quy ước được sử dụng bởi hầu hết thư viện phổ biến và tiêu chuẩn IETF RFC 9535.

Biểu Thức Lọc

Biểu thức lọc là nơi JSONPath thực sự trở nên mạnh mẽ. Chúng cho phép bạn chọn phần tử dựa trên điều kiện thay vì vị trí. Cú pháp lọc sử dụng [?(condition)], trong đó condition được đánh giá cho từng phần tử.

Toán Tử So Sánh

JSONPath hỗ trợ các toán tử so sánh sau trong biểu thức lọc:

Thư ViệnCài ĐặtExample
Rustserde_json_pathcargo add serde_json_path
!=Not equal to[?(@.category != "fiction")]
<Less than[?(@.price < 10)]
<=Less than or equal to[?(@.price <= 8.99)]
>Greater than[?(@.price > 15)]
>=Greater than or equal to[?(@.price >= 12.99)]
=~Regex match (some implementations)[?(@.author =~ /Tolkien/i)]

Ví Dụ Lọc Thực Tế

Sử dụng tài liệu mẫu của chúng tôi, đây là các biểu thức lọc thực tế và kết quả của chúng:

Find all books cheaper than $10:

< 10)]

Trả về sách "Sayings of the Century" ($8.95) và "Moby Dick" ($8.99).

Find all fiction books:

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

Trả về ba cuốn sách: "Sword of Honour", "Moby Dick" và "The Lord of the Rings".

Find books with an ISBN:

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

Trả về sách có thuộc tính isbn: "Moby Dick" và "The Lord of the Rings". Điều này là do bộ lọc kiểm tra sự tồn tại của thuộc tính.

Find the most expensive book:

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

Trả về "The Lord of the Rings" ($22.99).

Toán Tử Logic Trong Bộ Lọc

Bạn có thể kết hợp điều kiện bằng toán tử logic:

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

Biểu thức đầu tiên tìm sách tiểu thuyết dưới $10 (chỉ "Moby Dick"). Biểu thức thứ hai tìm sách trên $15 hoặc thuộc danh mục tham khảo (trả về "Sayings of the Century" và "The Lord of the Rings").

JSONPath và XPath

JSONPath được mô hình hóa rõ ràng theo XPath, và hai ngôn ngữ chia sẻ nhiều điểm tương đồng về khái niệm. Nếu bạn quen với xử lý XML, hiểu mối quan hệ này sẽ hữu ích.

FeatureJSONPathXPath
Root symbol$/
Child access.key['key']/element
Array index[0][1] (1-based)
Wildcard**
Recursive descent..//
Filter[?(condition)][condition]
AttributesNot applicable (JSON has no attributes)@attr
Current node@ (in filters).current()
ParentNot supported..
AxesNot supported13 axes (ancestor, following, etc.)
Data modelObjects and arraysElements, attributes, text nodes

Sự khác biệt chính là XPath hoạt động trên mô hình cây phong phú với phần tử, thuộc tính, nút văn bản, không gian tên và chỉ thị xử lý. JSONPath hoạt động trên mô hình đơn giản hơn với đối tượng (ánh xạ khóa-giá trị) và mảng (danh sách có thứ tự). Sự đơn giản này làm cho JSONPath dễ học hơn nhưng kém biểu cảm hơn XPath cho các truy vấn phức tạp.

JSONPath Trong Thực Tế

Kiểm Thử API

JSONPath không thể thiếu cho kiểm thử API. Khi bạn gửi yêu cầu đến API và nhận phản hồi JSON lớn, JSONPath cho phép bạn xác nhận giá trị cụ thể mà không cần điều hướng thủ công toàn bộ cấu trúc. Hầu hết công cụ kiểm thử API hỗ trợ JSONPath nguyên bản.

Ví dụ, trong kiểm thử bạn có thể xác minh giá của cuốn sách đầu tiên dưới $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"]

Chuyển Đổi Dữ Liệu

Khi tích hợp hệ thống sử dụng định dạng dữ liệu khác nhau, JSONPath giúp trích xuất và chuyển đổi trường cụ thể. Bạn có thể trích xuất giá trị từ một cấu trúc JSON và ánh xạ sang cấu trúc khác mà không cần viết code duyệt phức tạp.

Quản Lý Cấu Hình

File cấu hình phức tạp thường chứa JSON lồng sâu. JSONPath cho phép bạn truy vấn giá trị cấu hình cụ thể mà không cần tải và phân tích toàn bộ cấu trúc. Các công cụ như jq sử dụng cú pháp giống JSONPath để xử lý JSON trong pipeline dòng lệnh.

Giám Sát và Cảnh Báo

Trong hệ thống quan sát, truy vấn JSONPath có thể trích xuất metric từ log định dạng JSON và phản hồi API. Bạn có thể thiết lập cảnh báo kích hoạt khi truy vấn JSONPath trả về giá trị vượt ngưỡng.

Triển Khai JSONPath

JSONPath có sẵn trong hầu hết mọi ngôn ngữ lập trình. Đây là các thư viện phổ biến nhất:

LanguageLibraryInstallation
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

Ví Dụ 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

Mẹo chuyên nghiệp: Sử dụng JSONPath để kiểm thử API. Đặt assertions trên các trường cụ thể trong phản hồi JSON mà không cần phân tích toàn bộ response body. Hầu hết framework kiểm thử API như REST Assured, SuperTest và Karate hỗ trợ JSONPath nguyên bản.

Cạm Bẫy và Mẹo Phổ Biến

Năm 2024, IETF đã công bố RFC 9535, chính thức chuẩn hóa JSONPath. Đặc tả này giải quyết nhiều điểm không rõ ràng và không nhất quán tồn tại giữa các triển khai. Các khía cạnh chính của tiêu chuẩn bao gồm:

Nếu bạn đang bắt đầu dự án mới, ưu tiên thư viện triển khai RFC 9535 để có khả năng tương thích tối đa và hành vi có thể dự đoán.

Cần truy vấn dữ liệu JSON nhanh chóng? Hãy dùng thử công cụ kiểm tra JSONPath trực tuyến miễn phí của chúng tôi, đánh giá biểu thức theo thời gian thực trên tài liệu JSON của bạn.

Dùng Thử Trình Kiểm Tra JSONPath Trực Tuyến

Tiêu Chuẩn IETF: RFC 9535

Ví Dụ Python

JSONPath là ngôn ngữ truy vấn JSON, tương tự như XPath đối với XML. Nó sử dụng biểu thức đường dẫn để điều hướng và trích xuất giá trị cụ thể từ tài liệu JSON. Biểu thức JSONPath như $.store.book[0].title cho phép bạn định vị chính xác dữ liệu trong cấu trúc JSON lồng phức tạp mà không cần viết code phân tích tùy chỉnh.

JSONPath là gì?

JSONPath được thiết kế cho cấu trúc đối tượng và mảng của JSON, trong khi XPath được thiết kế cho cây phần tử và thuộc tính của XML. JSONPath sử dụng $ làm nút gốc, ký hiệu dấu chấm truy cập đối tượng, ký hiệu dấu ngoặc truy cập mảng. XPath sử dụng / để phân cách đường dẫn, @ để truy cập thuộc tính. JSONPath đơn giản hơn nhưng ít tính năng hơn XPath.

JSONPath khác XPath như thế nào?

Dấu chấm đôi (..) trong JSONPath là toán tử recursive descent. Nó tìm kiếm khóa được đặt tên ở tất cả cấp của cấu trúc JSON, không chỉ con trực tiếp. Ví dụ, $..author tìm tất cả khóa author ở bất kỳ đâu trong toàn bộ tài liệu, bất kể chúng lồng sâu đến đâu.

Dấu chấm đôi (..) trong JSONPath có nghĩa là gì?

<, ><=, >< 10)] tìm tất cả sách dưới $10.

JSONPath có thể lọc dữ liệu theo điều kiện không?

JSONPath ban đầu được Stefan Goessner đề xuất năm 2007 mà không có đặc tả chính thức, dẫn đến khác biệt giữa các triển khai. Năm 2024, IETF đã công bố RFC 9535 chính thức chuẩn hóa JSONPath. Các triển khai hiện đại đang hội tụ về tiêu chuẩn này, nhưng một số thư viện cũ hơn có thể có khác biệt cú pháp nhẹ.