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