ToolDeck

JSONPath测试器

针对JSON数据测试JSONPath表达式并查看匹配结果

加载示例

JSON输入

结果

本地运行 · 粘贴密钥安全无忧
结果将显示在此处…

什么是JSONPath?

JSONPath是一种用于从JSON文档中提取值的查询语言。它最初由Stefan Goessner于2007年提出,作为XML的XPath的类比工具,JSONPath允许你编写类似$.store.book[*].author的表达式,无需编写循环或手动遍历代码即可选取book数组中的所有author字段。该语言于2024年2月由IETF发布为RFC 9535正式标准化。

JSONPath表达式始终以$开头,代表文档的根节点。从根节点起,你可以链式添加选择器:使用点符号访问对象键,使用括号符号访问数组索引,使用通配符选取所有子节点,以及使用递归下降操作符(..)搜索嵌套的每一层。过滤表达式如[?(@.price < 10)]可让你根据对元素值求值的条件来选取元素。

JSONPath被广泛应用于Postman等API测试工具、Datadog和Splunk等可观测性平台、Apache NiFi等工作流引擎,以及JavaScript、Python、Go、Java和C#的编程库中。在将表达式嵌入代码或配置文件之前,先针对真实数据进行测试,可以避免JSON结构与预期不符时发生的隐性错误。

为什么使用此JSONPath测试器?

手动编写JSONPath表达式容易出错。一个缺失的点、错误的括号类型或不正确的过滤语法都可能导致返回空结果且没有任何错误提示。此工具为你提供即时的可视化反馈,告诉你表达式匹配了哪些内容。

即时结果
粘贴JSON,输入表达式,实时查看匹配值更新。无需运行脚本或刷新页面来检查查询结果。
🔒
隐私优先
所有求值均在浏览器中运行。你的JSON数据从不离开本机,因此可以放心地针对包含凭据的生产API响应或配置文件测试表达式。
📋
直接复制结果
一键将匹配输出复制为JSON。无需重新格式化即可粘贴到测试断言、文档或API响应示例中。
🛠️
无需配置
无需安装npm包,无需创建Python虚拟环境。打开页面,粘贴数据,开始查询。支持任何带浏览器的设备。

JSONPath使用场景

前端开发
在将API响应接入React状态或Vue计算属性之前,从中提取所需的精确嵌套值。先针对真实API载荷测试路径表达式。
后端API测试
Postman和REST-assured使用JSONPath断言响应体。在将断言表达式复制到测试脚本之前,先在此处构建和验证,减少调试周期。
DevOps配置
Kubernetes自定义资源定义、AWS Step Functions和Terraform数据源接受JSONPath表达式,用于从JSON输出中提取值。在部署之前验证路径。
QA测试自动化
为契约测试和集成测试编写基于JSONPath的断言。当JSON结构包含可选字段或可空字段时,验证表达式能否正确匹配预期值。
数据管道提取
Apache NiFi、Logstash和自定义ETL脚本使用JSONPath从半结构化日志数据和事件流中提取字段。在管道部署前针对样本载荷测试表达式。
学习与实验
JSONPath初学者和开发者可以针对示例JSON尝试不同表达式,无需本地环境即可理解通配符、递归下降和过滤器的工作方式。

JSONPath语法参考

RFC 9535定义了标准的JSONPath语法。下表涵盖了大多数查询中会用到的操作符。所有表达式均以$(根节点)开头,并链式添加一个或多个选择器来导航文档结构。

操作符描述示例
$Root element$.store
.keyChild property$.store.book
[n]Array index (zero-based)$.store.book[0]
[*]All elements in array/object$.store.book[*]
..Recursive descent$..author
[start:end]Array slice$.store.book[0:2]
[?()]Filter expression$.store.book[?(@.price<10)]
@Current node (inside filter)$.store.book[?(@.isbn)]

JSONPath vs jq vs XPath

JSONPath、jq和XPath针对不同格式和使用场景解决同一个问题(查询结构化数据)。JSONPath面向JSON,可作为库在大多数语言中使用。jq是一个独立的CLI工具,拥有自己的图灵完备过滤语言。XPath面向XML,是W3C规范体系的一部分。

特性JSONPathjqXPath
数据格式JSONJSONXML
访问第一个元素$.store.book[0].store.book[0]/store/book[1]
递归搜索$..price.. | .price?//price
过滤表达式[?(@.price<10)]select(.price < 10)[price<10]
规范RFC 9535stedolan.github.ioW3C XPath 3.1

代码示例

如何在常用语言和工具中求值JSONPath表达式。每个示例均使用相同的书店JSON结构以便对比。

JavaScript (jsonpath-plus)
import { JSONPath } from 'jsonpath-plus';

const data = {
  store: {
    book: [
      { title: 'Moby Dick', price: 8.99 },
      { title: 'The Great Gatsby', price: 12.99 }
    ]
  }
};

// Get all book titles
JSONPath({ path: '$.store.book[*].title', json: data });
// → ['Moby Dick', 'The Great Gatsby']

// Recursive descent — find every price in the document
JSONPath({ path: '$..price', json: data });
// → [8.99, 12.99]

// Filter — books under $10
JSONPath({ path: '$.store.book[?(@.price < 10)]', json: data });
// → [{ title: 'Moby Dick', price: 8.99 }]
Python (jsonpath-ng)
from jsonpath_ng.ext import parse
import json

data = {
    "store": {
        "book": [
            {"title": "Moby Dick", "price": 8.99},
            {"title": "The Great Gatsby", "price": 12.99}
        ]
    }
}

# Get all book titles
expr = parse("$.store.book[*].title")
titles = [match.value for match in expr.find(data)]
# → ['Moby Dick', 'The Great Gatsby']

# Recursive descent — all prices
expr = parse("$..price")
prices = [match.value for match in expr.find(data)]
# → [8.99, 12.99]

# Filter — books under $10
expr = parse("$.store.book[?price < 10]")
cheap = [match.value for match in expr.find(data)]
# → [{"title": "Moby Dick", "price": 8.99}]
Go (ohler55/ojg)
package main

import (
    "fmt"
    "github.com/ohler55/ojg/jp"
    "github.com/ohler55/ojg/oj"
)

func main() {
    src := `{
        "store": {
            "book": [
                {"title": "Moby Dick", "price": 8.99},
                {"title": "The Great Gatsby", "price": 12.99}
            ]
        }
    }`

    obj, _ := oj.ParseString(src)

    // Get all book titles
    expr, _ := jp.ParseString("$.store.book[*].title")
    results := expr.Get(obj)
    fmt.Println(results)
    // → [Moby Dick The Great Gatsby]

    // Recursive descent — all prices
    expr2, _ := jp.ParseString("$..price")
    fmt.Println(expr2.Get(obj))
    // → [8.99 12.99]
}
CLI (jq alternative syntax)
# jq uses its own syntax, not JSONPath, but solves the same problem.
# Mapping common JSONPath patterns to jq:

# $.store.book[*].title → get all titles
echo '{"store":{"book":[{"title":"Moby Dick"},{"title":"Gatsby"}]}}' | \
  jq '.store.book[].title'
# → "Moby Dick"
# → "Gatsby"

# $..price → recursive descent for "price" keys
echo '{"a":{"price":1},"b":{"price":2}}' | \
  jq '.. | .price? // empty'
# → 1
# → 2

# Filter: books where price < 10
echo '{"store":{"book":[{"title":"A","price":8},{"title":"B","price":12}]}}' | \
  jq '.store.book[] | select(.price < 10)'
# → {"title":"A","price":8}

常见问题

JSONPath和jq有什么区别?
JSONPath是一种查询语言,设计用于作为库嵌入应用程序中。它使用路径表达式从JSON文档中返回匹配值。jq是一个独立的命令行工具,拥有完整的编程语言,用于转换JSON,包括条件语句、函数和字符串插值。当需要在代码或Postman等工具中嵌入查询时使用JSONPath;当需要进行临时命令行数据转换时使用jq。
JSONPath是官方标准吗?
是的。IETF于2024年2月发布了RFC 9535("JSONPath: Query Expressions for JSON")。在此之前,JSONPath仅以Stefan Goessner于2007年提出的非正式规范形式存在,这导致了各实现之间的不一致。RFC 9535定义了语法、语义和互操作性的规范化格式。
JSONPath中的递归下降(..)如何工作?
递归下降操作符(..)在JSON文档的每一层中搜索其后跟随的键。例如,$..price返回所有与键"price"关联的值,无论其嵌套有多深。它等效于深度优先遍历并收集匹配节点。请注意,在大型文档中,递归下降可能返回大量结果,且可能比直接路径慢。
JSONPath能修改JSON数据吗?
不能。JSONPath是只读查询语言。它只能选取和返回值,不能插入、更新或删除节点。若要根据JSONPath表达式修改JSON,需要在查询之后使用编程语言的JSON操作函数。某些库(如Python的jsonpath-ng)在匹配对象上提供了set()方法,但这是库扩展,不属于JSONPath规范。
JSONPath过滤表达式中的@符号是什么意思?
@符号指代过滤表达式中当前被求值的节点。在$.store.book[?(@.price < 10)]中,过滤器遍历book数组的每个元素,@代表每个book对象。@.price访问当前book的price字段。没有@,过滤器就不知道要检查哪个节点的属性。
如何在JSONPath中处理包含特殊字符或空格的键?
使用带引号的括号符号:$['store']['book title']。括号符号适用于任何键,包括含有点、空格或Unicode字符的键。点符号($.store.key)只适用于有效标识符(字母、数字、下划线)的键。RFC 9535要求实现同时支持单引号和双引号括号符号。
为什么我的JSONPath表达式返回空结果?
最常见的原因有:键名拼写错误(JSONPath区分大小写)、对含有特殊字符的键使用了点符号、开头缺少$根符号,或者将单个对象误认为数组。将JSON粘贴到测试工具中,先尝试更简单的子表达式(如$.store),逐段验证路径正确解析后再添加更多选择器。