有效的json路径表达式是符合特定语法规范的字符串,如$..name或$.users[0].email,它不属于标准json,而是jsonpath查询语言的语法;不同实现(如jayway、nlohmann/json)支持的语法规则差异大,其中rfc 6901定义的json pointer(如/users/0/email)可通过构造json::json_pointer并捕获异常来可靠校验,而通用jsonpath无法仅靠正则完全验证,必须依赖对应解析器执行dry-run。

什么是有效的JSON路径表达式
JSON路径表达式(如 $..name、$.users[0].email)不是标准JSON的一部分,而是 JSONPath 查询语言的语法。C++ 标准库不内置 JSONPath 解析器,所以「判断是否有效」本质上是判断字符串是否符合某一种 JSONPath 实现的语法规则——而不同实现(如 Jayway JsonPath、RapidJSON 的 Pointer、nlohmann/json 的 json_pointer)支持的语法差异很大。
你得先明确:你要校验的是 JSON Pointer(RFC 6901,形如 /users/0/email),还是更通用的 JSONPath 表达式(形如 $.store.book[*].title)。前者有明确文法,后者没有统一标准,几乎无法靠正则完全验证。
用 nlohmann/json 验证 JSON Pointer 是否合法
nlohmann/json 提供了 json::json_pointer 构造函数,它会在构造时抛出 nlohmann::json::parse_error 异常(错误码为 parse_error::syntax_error)如果输入不符合 RFC 6901 规范。这是最可靠、最轻量的方式。
注意:json_pointer 要求以 / 开头,且内部片段必须是 URI 编码后的 token(允许 ~0、~1 转义),不支持 $、..、[?(@.x)] 等 JSONPath 特性。
- ✅ 合法:
""(空指针)、"/a/b"、"/0"、"/a~1b" - ❌ 非法:
"$.a.b"、"$..book"、"/a/b/"(末尾斜杠)、"/a//b"(双斜杠)、"/a~"(不完整转义)
实操代码:
try {
nlohmann::json::json_pointer{path_str}; // path_str 是 std::string
return true;
} catch (const nlohmann::json::parse_error&) {
return false;
}
不要用正则硬写 JSONPath 语法校验
JSONPath(尤其 Jayway 风格)语法自由度高:支持递归下降 ..、过滤器 [?(@.price 、脚本表达式 <code>[#].name、通配符 * 和数组切片 [0:5]。这些特性让完整语法校验等价于写一个简易解析器——正则根本无法处理嵌套括号、引号平衡、运算符优先级。
如果你只是想「快速拦截明显非法的字符串」,可以加一层轻量预筛:
- 拒绝空字符串或只含空白
- 拒绝包含未闭合的
[或((但注意[?(@.x)]是合法的) - 拒绝出现
;、{、}、=(除非你明确支持某种扩展语法) - 拒绝以
..开头但不含$(如..name通常非法,$..name才合法)
但这只是 heuristic 拦截,不能替代真实解析。真要验证,必须用对应 JSONPath 库(如 jsoncons 或绑定 jsonpath-ng 的 Python 子进程)做 dry-run 解析。
区分场景:你是要解析,还是要仅校验格式?
绝大多数情况下,你真正需要的不是「判断路径字符串是否语法正确」,而是「这个路径能否在目标 JSON 上安全求值」。后者必须结合具体 JSON 数据和解析器执行 —— 因为即使语法合法,也可能因数据结构不匹配而失败(比如对非对象用 .field,对非数组用 [0])。
所以建议:
- 若用
json_pointer:直接构造,捕获异常即可 - 若用 JSONPath:跳过格式校验,直接调用
evaluate并检查返回结果是否为空或抛异常 - 若需提前提示用户错误,把解析器的错误信息(如
jsoncons::jsonpath::jsonpath_error的 what())提取出来展示,比自定义校验更准确
RFC 6901 的 json_pointer 是唯一能靠构造函数+异常做可靠校验的;其余都绕不开实际解析器的执行上下文。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!











