skyscanner / jsonpath
Requires
- php: >=5.4
Requires (Dev)
- phpunit/phpunit: ~4.0
- sami/sami: >=3.3.0
- satooshi/php-coveralls: >=1.0.1
- dev-master
- 3.0
- 2.1
- 2.0
- 1.3.1
- 1.3
- 1.2
- 1.1
- 1.0
- 0.8
- 0.7.3
- 0.7.2
- 0.7.1
- 0.7.0
- 0.6.0
- 0.5.1
- 0.5.0
- dev-normalize_length_op
- dev-fix_53_revert_length_functionality
- dev-refactor_extract_private_methods
- dev-add_support_for_not_symbol
- dev-44-add_symbol_or_and_operators
- dev-fix-#24_proper_serializarion_of_objects_and_arrays_when_empty
This package is not auto-updated.
Last update: 2023-03-05 20:26:54 UTC
README
这是PHP的JSONPath实现。
此实现包含规范中的所有元素,除了()
运算符(规范中有$..a[(@.length-1)]
,但可以使用$..a[-1]
实现,后者更简单)。
如果查询没有匹配项,它将返回一个空数组。
特性
此实现具有以下特性:
- 正则表达式匹配键(例如:
$.*[?(/^bo{2}k$/)]
或$[?(/a\wthors/)]
)。 - 正则表达式匹配值比较(例如:
$.store.book[?(@.author =~ /.*Tolkien/)]
) - 对于子运算符
[]
,除非字段名称是非有效的JavaScript变量名称,否则不需要用引号包围子名称(例如:$[store][book, bicycle]
)。 .length
可用于获取字符串的长度、获取数组的长度以及检查节点是否有子节点。in
运算符允许在指定列表中过滤值:$..[?(@.author in ["Nigel Rees", "Evelyn Waugh", $.store.book[3].author])]}
- 面向对象实现。
- 实现
get
、set
和add
操作。 - 实现了魔法方法
__get
:$obj->{'$...'}
.__set
:$obj->{'$...'} = $val
.__toString
:echo $obj
打印JsonObject的JSON表示。
- 不使用
eval()
。
安装
要安装JsonPath,您需要在项目中使用Composer。有关安装信息,请参阅文档。
composer require galbar/jsonpath
用法
在您使用它的每个文件中添加
use JsonPath\JsonObject;
现在您可以创建JsonObject的实例并使用它
// $json can be a string containing json, a PHP array, a PHP object or null. // If $json is null (or not present) the JsonObject will be empty. $jsonObject = new JsonObject(); // or $jsonObject = new JsonObject($json); // get $obj->get($jsonPath); $obj->{'$.json.path'}; // set $obj->set($jsonPath, $value); $obj->{'$.json.path'} = $value; // get the json representation $obj->getJson(); $str = (string)$obj; echo $obj; // get the PHP array representation $obj->getValue(); // add values $obj->add($jsonPath, $value[, $field]); // remove values $obj->remove($jsonPath, $field);
SmartGet
在创建JsonObject的新实例时,您可以向构造函数传递第二个参数。这将设置实例的行为以使用SmartGet。
SmartGet所做的是确定给定的JsonPath在某个点是否分支,如果是,它将像通常一样处理;否则,它将直接返回由给定路径指向的值(不是包含它的数组)或如果未找到,则返回false
。
GetJsonObjects
有时您需要访问具有长前缀的子对象中的多个值(例如:$.a.very.long.prefix.for.[*].object
),在这种情况下,您首先获取该对象并将其转换为JsonObject,然后访问其属性。
现在,如果您想编辑对象(设置或添加值)并希望这些更改影响原始对象,则可以通过使用JsonObject::getJsonObjects($jsonpath)
来完成。此方法的工作方式与get相同,但它将返回结果作为包含对源JsonObject中值引用的JsonObject实例。
JsonPath 语言
该库实现了以下规范:
var_name¹ = /^\.([\p{L}\p{N}\_\$][\p{L}\p{N}\_\-\$]*|\*)(.*)/u
number = ([0-9]+(\.[0-9]*) | ([0-9]*\.[0-9]+))
string = ('\''.*?'\'' | '"'.*?'"')
boolean = ('true' | 'false')
regpattern = '/'.*?'/i?x?'
null = 'null'
index = -?[0-9]+
jsonpath = '$' operator*
childpath = '@' operator*
operator = (childname | childfilter | recursive) operator*
childname = '.' (var_name | '*')
childfilter = '[' ('*' | namelist | indexlist | arrayslice | filterexpr) ']'
recursive = '..' (var_name | childfilter | '*')
namelist = var_name (',' (var_name | '\'' .*? '\'' | '"' .*? '"'))*
indexlist = index (',' index)*
arrayslice = index? ':' index? ':' index?
filterexpr = '?(' ors ' | regpattern)'
ors = ands (' ' ( 'or' | '\|\|' ) ' ' ands)*
ands = expr (' ' ( 'and' | '&&' ) ' ' expr)*
expr = ( 'not ' | '! ' )? (value | comp | in_array)
comp = value ('==' | '!=' | '<' | '>' | '<=' | '>=' | '=~') value
value = (jsonpath | childpath | number | string | boolean | regpattern | null | length)
length = (jsonpath | childpath) '.length'
in_array = value 'in' '[' value (',' value)* ']'
¹var_name
:正则表达式大致翻译为“任何有效的JavaScript变量名”,还包括一些怪癖,如以数字开头或包含短横线(-
)的名称。
规范的限制
- value中的jsonpath不能包含
or
、and
或任何比较器。 - value中的Jsonpath返回集合的第一个元素或没有结果时返回
false
。 - 布尔运算不能与括号组合。
and
运算符先于or
运算符执行。这意味着a and 1 = b or c != d
与(a and 1) or (c != d)
相同。
点长度运算符.length
可以用来:
- 获取JsonObject中节点拥有的子节点数量:
$..*[?(@.length > 3)]
- 筛选具有子节点的节点:
$..*[?(@.length)]
- 或者筛选没有子节点(叶子节点)的节点:
$..*[?(not @.length)]
- 检查字符串的长度:
$.path.to[?(@.a.string.length > 10)]
- 获取字符串的长度:
$.path.to.field.length
- 获取数组的长度:
$.path.to.array.length
- 获取数组中数组的长度:
$.path.to.array[*].array[*].length
- 获取字符串数组中每个字符串的长度:
$.path.to.array[*].array[*].key.length
比较器:
==
、!=
、<
、>
、<=
、>=
按预期执行(按类型和值比较)。
=~
是一个正则表达式比较器,将左操作数与右操作数中的模式匹配。左边的值必须是字符串,右边的值必须是正则表达式。否则返回false
。
JsonPath 示例
考虑以下json
{ "store": { "book": [ { "category": "reference", "author": "Nigel Rees", "title": "Sayings of the Century", "price": 8.95, "available": true }, { "category": "fiction", "author": "Evelyn Waugh", "title": "Sword of Honour", "price": 12.99, "available": false }, { "category": "fiction", "author": "Herman Melville", "title": "Moby Dick", "isbn": "0-553-21311-3", "price": 8.99, "available": true }, { "category": "fiction", "author": "J. R. R. Tolkien", "title": "The Lord of the Rings", "isbn": "0-395-19395-8", "price": 22.99, "available": false } ], "bicycle": { "color": "red", "price": 19.95, "available": true } }, "authors": [ "Nigel Rees", "Evelyn Waugh", "Herman Melville", "J. R. R. Tolkien" ] }
JsonPath | 结果 |
---|---|
$.store.bicycle.price |
自行车的价格。 |
$.store.book[*] |
所有书籍。 |
$.store.book[1,3] |
第二本和第四本书。 |
$.store.book[1:3] |
从第二本书到第三本书。 |
$.store.book[:3] |
从第一本书到第三本书。 |
$.store.book[x:y:z] |
从x到y,步长为z的书籍。 |
$..book[?(@.category == 'fiction')] |
所有类别为'fiction'的书籍。 |
$..*[?(@.available == true)].price |
所有可用品的价格。 |
$..book[?(@.price < 10)].title |
所有价格低于10元的书籍的标题。 |
$..book[?(@.author==$.authors[3])] |
所有由“J. R. R. Tolkien”所著的书籍。 |
$[store] |
商店。 |
$['store'] |
商店。 |
$..book[*][title, 'category', "author"] |
所有书籍的标题、类别和作者。 |
$..book[?(@.author in [$.authors[0], $.authors[2]])] |
所有由“Nigel Rees”或“Herman Melville”所著的书籍。 |
$.store.book[?(@.category == 'fiction' and @.price < 10 or @.color == "red")].price |
小说类且价格低于10元或红色的书籍。(and 优先于or ) |
更多示例请参阅./tests/Galbar/JsonPath
文件夹。
测试
要从项目根目录运行测试:
php app/test.php <jsonpath> [<json文件>]
如果没有提供json文件,它默认为在此文件之前描述的json对象。
例如:
php app/test.php "$..*[?(@.category == 'fiction' and @.price < 10 or @.color == \"red\")].price"
结果应该是
[19.95,8.99]
准备编码
文档
要生成文档,请从项目根目录开始
php vendor/bin/sami.php update app/docgen.php