eboubaker / json-finder
一个库,可以在混合文本或HTML文档中查找json值,可以过滤和搜索json树,并将php对象转换为json而不需要'ext-json'扩展。
v1.2.0
2022-04-21 17:38 UTC
Requires
- php: >=7.4
Requires (Dev)
- ext-json: *
- phpunit/phpunit: ^9.5
README
一个库,可以在混合文本或HTML文档中查找json值,可以过滤和搜索json树,并将php对象转换为json而不需要'ext-json'扩展。
安装
使用composer安装库
composer require eboubaker/json-finder
快速入门
假设你想要抓取来自http响应的所有json(来自<script>标签)。
use Eboubaker\JSON\JSONFinder; $html = file_get_contents('http://www.youtube.com'); $finder = JSONFinder::make(); /** * @var \Eboubaker\JSON\JSONArray $foundEntries */ $foundEntries = $finder->findEntries($html); // associative array of all found json entries $associative = $foundEntries->assoc(); // 4th entry in the JSONArray $entry = $foundEntries[3]; // get json string of the first entry (similar to json_encode) $jsonString = strval($entry); // loop through entries of the JSONArray ($foundEntries) foreach($foundEntries as $key => $value) { // .... } // loop through every deeply nested value(not object or array) foreach($foundEntries->values() as $keyPath => $value) { // .... } // pretty print the json entry with indentation of 2 spaces echo $foundEntries->toReadableString(2);
值编码
你可以使用ext-json将php值编码为json字符串。
use Eboubaker\JSON\JSONObject; $phpvalue = [ "a" => "b", "e" => [ "f" => null, "h" => [ "i" => "j", "k" => [1, 2, 3e-13, ["x"=> 0.3]] ] ] ]; $obj = JSONObject::from($phpvalue); echo strval($obj);// '{"a":"b","e":{"f":null,"h":{"i":"j","k":[1,2,3.0E-13,{"x":0.3}]}}}'
JSON查询
你可以在json树内部搜索值。使用点表示法路径和通配符 "*
" "**
"。
use Eboubaker\JSON\JSONObject; $obj = JSONObject::from([ "meta" => [ "id" => "12345", "title" => "My Title", ], "video" => [ "id" => "12345", "formats" => [ [ "name" => "mp4", "url" => "https://example.com/video720.mp4", "resolution" => "1280x720", ], [ "name" => "mp4", "url" => "https://example.com/video1080.mp4", "resolution" => "1920x1080", ], [ "name" => "webm", "url" => "https://example.com/video720.webm", "resolution" => "1280x720", ], ] ] ]); $obj->getAll('formats'); // empty array [], $obj does not contain 'formats' path $result = $obj->getAll('meta.id'); // [0 => JSONValue("12345")] $video_id = $result[0]; // get all deep entries that contains an 'id' key $has_id = $obj->getAll('**.id'); // get all formats in 'video.formats' path $all_formats = $obj->getAll('video.formats.*'); // you can apply a filter to the results $mp4_formats = $obj->getAll('video.formats.*', fn($v) => $v->get('name')->equals('mp4')); // ['video.formats.0' => JSONObject({"name":"mp4","url":"https://example.com/video720.mp4","resolution":"1280x720"})] // return paths of found results as the keys in the result array $has_id = $obj->getAll('**.id', null, true); // ['meta.id' => JSONValue("12345"), 'video.id' => JSONValue("12345")]
查找JSON对象/数组
你可以使用JSONObject::search()
或JSONArray::search()
查找包含特定键的单个json对象/数组。
该方法接受一个路径列表,带可选值过滤器。
将返回包含所有提供路径的目标。
use Eboubaker\JSON\JSONObject; use Eboubaker\JSON\Contracts\JSONEntry; $object = JSONObject::from([ "response" => [ "hash" => "a5339be0849ced1ffe", "posts" => [ [ "id" => "1634", "likes" => 700, "text" => "Machine learning for beginners", ], [ "id" => "1234", "likes" => 200, "text" => "top 10 best movies of 2019", "comments" => [ [ "id" => "1134", "likes" => 2, "replies" => [], "content" => "thanks for sharing", ], [ "id" => "1334", "content" => "this video is bad", "likes" => 0, "replies" => [ [ "id" => "1435", "likes" => 0, "content" => "this is not true", ], [ "id" => "1475", "likes" => 0, "content" => "agree this is the worst", ] ], ] ], ] ] ] ]); // get first object which matches these paths and filters. $comment_with_likes = $object->search([ "content", "likes" => fn(JSONEntry $v) => $v->value() > 0 ]); echo $comment_with_likes;// {"id":"1134","likes":2,"replies":[],"content":"thanks for sharing"} $post_with_comment_replies = $object->search([ "comments.*.replies" ]); echo $post_with_comment_replies['id'];// "1234" // more than 0 replies $comment_with_replies = $object->search([ "replies.*" ]); echo $comment_with_replies['id'];// "1334" $comment_with_bad_words = $object->search([ "content" => fn(JSONEntry $v) => $v->matches('/worst|bad/') ]); echo $comment_with_bad_words['id'];// "1334"
控制JSONFinder的结果
你可以向JSONFinder工厂添加标志来设置JSONFinder将返回的值的允许类型。
例如,如果你想也将javascript对象包括在结果中,可以添加T_JS标志。这将也会匹配javascript对象键或用单引号'
引用的javascript字符串。
use Eboubaker\JSON\JSONFinder; // this finder can also find javascript objects/arrays $finder = JSONFinder::make(JSONFinder::T_ALL_JSON | JSONFinder::T_JS); $finder->findEntries("let data = {jskey: 1};")->first();// JSONObject({"jskey":1}) $finder->findEntries("var x = Object.freez({'js-key': 'js string'})")->first();// JSONObject({"js-key":"js string"})
所有其他函数都有PHPDoc自文档。