JSONPath概括及相关内容

JSONPath - XPath for JSON

XML 的一个经常强调的优点是可以使用大量工具来分析、转换和有选择地从 XML 文档中提取数据。XPath就是这些功能强大的工具之一。

现在是时候想知道,是否需要像XPath4JSON这样的东西,以及它可以解决什么问题。

  • 数据可以交互方式找到并从客户端上的JSON结构中提取出来,而无需特殊的脚本。
  • 客户端请求的JSON数据可以缩减到服务器上的相关部分,这样可以最大限度地减少服务器响应的带宽使用。

如果我们从现有的JSON结构中挑选部分的工具,那么就会出现一些问题。它应该如何完成它的工作?JSONPath 表达式的外观如何?

由于 JSON 是 C 系列编程语言数据的自然表示形式,因此特定语言具有访问 JSON 结构的本机语法元素的可能性很高。

以下 XPath 表达式

/store/book[1]/title

看起来像

x.store.book[0].title

x['store']['book'][0]['title']

在Javascript,Python和PHP中,带有一个保存JSON结构的变量。在这里,我们观察到,特定语言通常具有已经内置的基本XPath功能。x

有问题的JSONPath工具应该…

  • 自然地基于这些语言特征。
  • 仅涵盖 XPath 1.0 的基本部分。
  • 在代码大小和内存消耗方面是轻量级的。
  • 提高运行时效率。

JSONPath 表达式

JSONPath 表达式引用 JSON 结构的方式始终与 XPath 表达式与 XML 文档结合使用的方式相同。由于 JSON 结构通常是匿名的,并且不一定具有“根成员对象”,因此 JSONPath 假定分配给外部级别对象的抽象名称。$

JSONPath 表达式可以使用表示法

$.store.book[0].title

括号表示法

$['store']['book'][0]['title']

用于输入路径。内部或输出路径将始终转换为更通用的括号表示法。

JSONPath 允许将通配符符号 * 用于成员名称和数组索引。它借用了 E4X 中的后代运算符 ‘…’ 和 ECMASCRIPT 4 中的*数组切片语法*建议。[start:end:step]

基础脚本语言的表达式可用作显式名称或索引的替代方法,如(<expr>)

$.store.book[(@.length-1)].title

对当前对象使用符号“@”。通过以下语法支持筛选器表达式:如?(<boolean expr>)

$.store.book[?(@.price < 10)].title

以下是 JSONPath 语法元素与其 XPath 对应元素的完整概述和并排比较。

断续器 JSONPath 描述
/ $ 根对象/元素
. @ 当前对象/元素
/ .[] 子运算符
.. none 父运算符
// .. 递归下降。JSONPath 从 E4X 借用了这种语法。
* * 通配符。所有对象/元素,无论其名称如何。
@ none 属性访问。JSON 结构没有属性。
[] [] 下标运算符。XPath 使用它来循环访问元素集合和谓词。在Javascript和JSON中,它是本机数组运算符。
` ` [,]
none [start:end:step] 从 ES4 借用的数组片运算符。
[] ?() 应用筛选器(脚本)表达式。
none () 脚本表达式,使用基础脚本引擎。
() none 在 Xpath 中分组

XPath 提供的比此处列出的更多(非缩写语法、运算符和函数的位置路径)。此外,下标运算符在 Xpath 和 JSONPath 中的工作方式也存在显著差异。

  • XPath 表达式中的方括号始终对由上一个路径片段生成的节点集进行操作。指数始终从 1 开始。
  • 使用 JSONPath 方括号对上一个路径片段寻址的对象数组进行操作。指数始终从 0 开始。

JSONPath 示例

让我们通过更多示例来练习 JSONPath 表达式。我们从一个简单的 JSON 结构开始,该结构是在表示书店(原始 XML 文件)的 XML 示例之后构建的。

{ "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 结果
/store/book/author $.store.book[*].author 商店中所有书籍的作者
//author $..author 所有作者
/store/* $.store.* 商店里所有的东西,都是一些书和一辆红色的自行车。
/store//price $.store..price 商店里所有东西的价格。
//book[3] $..book[2] 第三本书
//book[last()] $..book[(@.length-1)]
$..book[-1:] 最后一本书按顺序排列。
//book[position()<3] $..book[0,1]
$..book[:2] 前两本书
//book[isbn] $..book[?(@.isbn)] 过滤所有带有 isbn 编号的图书
//book[price<10] $..book[?(@.price<10)] 过滤所有便宜于10的书籍
//* $..* XML 文档中的所有元素。JSON 结构的所有成员。

JSONPath 实现

JSONPath在Javascript中实现,用于客户端ide使用,并移植到PHP以便在服务器上使用。

用法

您需要做的就是下载其中任何一个文件

将其包含在程序中,并使用由单个函数组成的简单API。

jsonPath(obj, expr [, args])

参数:

obj (object|array) :表示 JSON 结构的对象。

expr (string) :表示 JSON 结构的对象。

expr (string) :JSONPath 表达式字符串。

args (object|undefined) :对象控制路径评估和输出。目前仅支持一个成员。

args.resultType ("VALUE"|"PATH") :使结果为匹配值(默认值)或规范化的路径表达式。

返回值:

(array|false) :

数组保存与输入路径表达式匹配的值或规范化路径表达式,可用于延迟求值。 如果没有匹配项。false

Javascript 示例

var o = { // }, // the ‘store’ JSON object from above res1 = jsonPath(o, “$…author”).toJSONString(), res2 = jsonPath(o, “$…author”, {resultType:“PATH”}).toJSONString();

PHP 示例

首先,我们需要将 JSON 字符串转换为 PHP 数组。我正在使用Michal MigurskiJSON解析器来实现这一点。

require_once(‘json.php’); // JSON parser require_once(‘jsonpath.php’); // JSONPath evaluator $json = ‘{ … }’; // JSON structure from above $parser = new Services_JSON(SERVICES_JSON_LOOSE_TYPE); $o = $parser->decode($json); $match1 = jsonPath($o, “$…author”); $match2 = jsonPath($o, “$…author”, array(“resultType” => “PATH”)); $res1 = $parser->encode($match1); $res2 = $parser->encode($match2);

结果

JavascriptPHP 示例都生成以下 JSON 数组(作为字符串):

res1: [ “Nigel Rees”, “Evelyn Waugh”, “Herman Melville”, “J. R. R. Tolkien” ] res2: [ “$[‘store’][‘book’][0][‘author’]”, “$[‘store’][‘book’][1][‘author’]”, “$[‘store’][‘book’][2][‘author’]”, “$[‘store’][‘book’][3][‘author’]” ]

请注意,的返回值是一个数组,它也是一个有效的 JSON 结构。因此,您可能希望再次应用于生成的结构,或者像使用它一样使用您喜欢的数组方法之一。jsonPath jsonPath sort

问题

  • 目前,JSONPath 表达式中只允许使用单引号。
  • JSONPath 位置内的脚本表达式当前未由 递归计算。只有全局和局部符号由简单的正则表达式展开。jsonPath $ @
  • 在没有匹配的情况下返回的替代方法可能是在将来返回空数组。jsonPath false

$.store.book[*].author 这个如果修改成$.store.book.author 是只能匹配上第一个book下的作者?