Я пытаюсь проанализировать JSON в PHP с помощью jsonpath ….
Мой JSON исходит из этого
https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs
(это слишком долго, чтобы вырезать / вставить здесь, но вы можете увидеть это в сеансе браузера ….)
JSON является действительным JSON (я проверил его, используя https://jsonlint.com/ … ).
Я пробовал выражение jsonpath, используя http://www.jsonquerytool.com/ и все, кажется, работает нормально, но когда я положил все в моем примере кода PHP ниже ….
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
require_once('json.php'); // JSON parser
require_once('jsonpath-0.8.0.php'); // JSONPath evaluator
$url = 'https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs';
$ch = curl_init();
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_PROXY, '');
$data = curl_exec($ch);
curl_close($ch);
$parser = new Services_JSON(SERVICES_JSON_LOOSE_TYPE);
$o = $parser->decode($data);
$xpath_for_parsing = '$..aziende[?(@.descrizione=="A.S.U.I. - Trieste")]..prontoSoccorsi[?(@.descrizione=="Pronto Soccorso e Terapia Urgenza Trieste")]..dipartimenti[?(@.descrizione=="Pronto Soccorso Maggiore")]..codiciColore[?(@.descrizione=="Bianco")]..situazionePazienti..numeroPazientiInAttesa';
$match1 = jsonPath($o, $xpath_for_parsing);
//print_r($match1);
$match1_encoded = $parser->encode($match1);
print_r($match1_encoded);
$match1_decoded = json_decode($match1_encoded);
//print_r($match1_decoded);
if ($match1_decoded[0] != '') {
return $match1_decoded[0];
}
else {
return "N.D.";
}
?>
… никакие значения не печатаются .. только «ложное» значение.
Что-то идет не так в моем выражении jsonpath, когда я помещаю это в мой PHP-код: эта ошибка заключается в следующем
Warning: Missing argument 3 for JsonPath::evalx(), called in /var/www/html/OpenProntoSoccorso/Test/jsonpath-0.8.0.php on line 84 and defined in /var/www/html/OpenProntoSoccorso/Test/jsonpath-0.8.0.php on line 101
Notice: Use of undefined constant descrizione - assumed 'descrizione' in /var/www/html/OpenProntoSoccorso/Test/jsonpath-0.8.0.php(104) : eval()'d code on line 1
Вероятно, мне нужно уйти / процитировать мой jsonpath, чтобы использовать его в PHP, но я не знаю, как … любое предложение приветствуется …
ПРИМЕЧАНИЕ: мне нужно использовать выражения jsonpath, такие как ?(@.descrizione=="A.S.U.I. - Trieste")
и я не могу использовать «позиционный» путь JSON …
Я также пытался использовать jsonpath-0.8.3.php отсюда https://github.com/ITS-UofIowa/jsonpath/blob/master/jsonpath.php, но ничего не меняется …
Предложения?
Заранее спасибо …
xpath слишком сложен для вашей задачи и вообще излишним …
просто используйте стандарт json_decode()
, получите эквивалентный объект PHP и перемещайтесь по нему, используя циклы и регулярные выражения stardard для / while
Также я думаю, что ваш вопрос вводит в заблуждение, ваша проблема не в разборе JSON (это делается json_decode()
автоматически), ваша проблема заключается в извлечении из него некоторых данных с помощью xpath.
Если вам нужно спуститься в точный узел JSON (или набор узлов), почему вы не делаете это с помощью циклов for и регулярных выражений?
вы можете использовать json_decode для преобразования его в собственный массив php, затем вы можете использовать hhb_xml_encode (из https://stackoverflow.com/a/43697765/1067003 ) для преобразования массива в xml, затем вы можете использовать DOMDocument :: loadHTML для преобразования XML в DOMDocument, затем вы можете использовать DOMXPath :: query для поиска по нему с помощью XPaths …
пример:
<?php
declare(strict_types = 1);
header ( "content-type: text/plain;charset=utf8" );
require_once ('hhb_.inc.php');
$json_raw = (new hhb_curl ( '', true ))->exec ( 'https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs' )->getStdOut ();
$parsed = json_decode ( $json_raw, true );
// var_dump ( $parsed );
$xml = hhb_xml_encode ( $parsed );
// var_dump($xml);
$dom = @DOMDocument::loadHTML ( $xml );
$dom->formatOutput = true;
$xp = new DOMXPath ( $dom );
$elements_for_parsing = $xp->query ( '//aziende/descrizione[text()=' . xpath_quote ( 'A.S.U.I. - Trieste' ) . ']|//prontosoccorsi/descrizione[text()=' . xpath_quote ( 'Pronto Soccorso e Terapia Urgenza Trieste' ) . ']|//dipartimenti/descrizione[text()=' . xpath_quote ( 'Pronto Soccorso Maggiore' ) . ']|//codicicolore/descrizione[text()=' . xpath_quote ( 'Bianco' ) . ']|//situazionepazienti|//numeroPazientiInAttesa' );
// var_dump ( $elements_for_parsing,$dom->saveXML() );
foreach ( $elements_for_parsing as $ele ) {
var_dump ( $ele->textContent );
}
// based on https://stackoverflow.com/a/1352556/1067003
function xpath_quote(string $value): string {
if (false === strpos ( $value, '"' )) {
return '"' . $value . '"';
}
if (false === strpos ( $value, '\'' )) {
return '\'' . $value . '\'';
}
// if the value contains both single and double quotes, construct an
// expression that concatenates all non-double-quote substrings with
// the quotes, e.g.:
//
// concat("'foo'", '"', "bar")
$sb = 'concat(';
$substrings = explode ( '"', $value );
for($i = 0; $i < count ( $substrings ); ++ $i) {
$needComma = ($i > 0);
if ($substrings [$i] !== '') {
if ($i > 0) {
$sb .= ', ';
}
$sb .= '"' . $substrings [$i] . '"';
$needComma = true;
}
if ($i < (count ( $substrings ) - 1)) {
if ($needComma) {
$sb .= ', ';
}
$sb .= "'\"'";
}
}
$sb .= ')';
return $sb;
}
function hhb_xml_encode(array $arr, string $name_for_numeric_keys = 'val'): string {
if (empty ( $arr )) {
// avoid having a special case for <root/> and <root></root> i guess
return '';
}
$is_iterable_compat = function ($v): bool {
// php 7.0 compat for php7.1+'s is_itrable
return is_array ( $v ) || ($v instanceof \Traversable);
};
$isAssoc = function (array $arr): bool {
// thanks to Mark Amery for this
if (array () === $arr)
return false;
return array_keys ( $arr ) !== range ( 0, count ( $arr ) - 1 );
};
$endsWith = function (string $haystack, string $needle): bool {
// thanks to MrHus
$length = strlen ( $needle );
if ($length == 0) {
return true;
}
return (substr ( $haystack, - $length ) === $needle);
};
$formatXML = function (string $xml) use ($endsWith): string {
// there seems to be a bug with formatOutput on DOMDocuments that have used importNode with $deep=true
// on PHP 7.0.15...
$domd = new DOMDocument ( '1.0', 'UTF-8' );
$domd->preserveWhiteSpace = false;
$domd->formatOutput = true;
$domd->loadXML ( '<root>' . $xml . '</root>' );
$ret = trim ( $domd->saveXML ( $domd->getElementsByTagName ( "root" )->item ( 0 ) ) );
assert ( 0 === strpos ( $ret, '<root>' ) );
assert ( $endsWith ( $ret, '</root>' ) );
$full = trim ( substr ( $ret, strlen ( '<root>' ), - strlen ( '</root>' ) ) );
$ret = '';
// ... seems each line except the first line starts with 2 ugly spaces,
// presumably its the <root> element that starts with no spaces at all.
foreach ( explode ( "\n", $full ) as $line ) {
if (substr ( $line, 0, 2 ) === ' ') {
$ret .= substr ( $line, 2 ) . "\n";
} else {
$ret .= $line . "\n";
}
}
$ret = trim ( $ret );
return $ret;
};
// $arr = new RecursiveArrayIterator ( $arr );
// $iterator = new RecursiveIteratorIterator ( $arr, RecursiveIteratorIterator::SELF_FIRST );
$iterator = $arr;
$domd = new DOMDocument ();
$root = $domd->createElement ( 'root' );
foreach ( $iterator as $key => $val ) {
// var_dump ( $key, $val );
$ele = $domd->createElement ( is_int ( $key ) ? $name_for_numeric_keys : $key );
if (! empty ( $val ) || $val === '0') {
if ($is_iterable_compat ( $val )) {
$asoc = $isAssoc ( $val );
$tmp = hhb_xml_encode ( $val, is_int ( $key ) ? $name_for_numeric_keys : $key );
// var_dump ( $tmp );
// die ();
$tmp = @DOMDocument::loadXML ( '<root>' . $tmp . '</root>' );
foreach ( $tmp->getElementsByTagName ( "root" )->item ( 0 )->childNodes ?? [ ] as $tmp2 ) {
$tmp3 = $domd->importNode ( $tmp2, true );
if ($asoc) {
$ele->appendChild ( $tmp3 );
} else {
$root->appendChild ( $tmp3 );
}
}
unset ( $tmp, $tmp2, $tmp3 );
if (! $asoc) {
// echo 'REMOVING';die();
// $ele->parentNode->removeChild($ele);
continue;
}
} else {
$ele->textContent = $val;
}
}
$root->appendChild ( $ele );
}
$domd->preserveWhiteSpace = false;
$domd->formatOutput = true;
$ret = trim ( $domd->saveXML ( $root ) );
assert ( 0 === strpos ( $ret, '<root>' ) );
assert ( $endsWith ( $ret, '</root>' ) );
$ret = trim ( substr ( $ret, strlen ( '<root>' ), - strlen ( '</root>' ) ) );
// seems to be a bug with formatOutput on DOMDocuments that have used importNode with $deep=true..
$ret = $formatXML ( $ret );
return $ret;
}
пс, линии require_once ('hhb_.inc.php');
просто выбираем url и помещаем json в $ json_raw (используя сжатую передачу gzip для ускорения работы между прочим), заменяем его на то, что вы хотите, чтобы извлечь его в $ json_raw, фактическая библиотека curl, которую я использовал из https://github.com/divinity76/hhb_.inc.php/blob/master/hhb_.inc.php#L477
$json_raw = (new hhb_curl ( '', true ))->exec ( 'https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs' )->getStdOut ();
в настоящее время он печатает:
string(18) "A.S.U.I. - Trieste"string(41) "Pronto Soccorso e Terapia Urgenza Trieste"string(9) "121200:14"string(10) "181400:254"string(6) "Bianco"string(7) "200:292"string(5) "00:00"string(24) "Pronto Soccorso Maggiore"string(7) "3300:15"string(6) "Bianco"string(8) "6200:584"string(5) "00:00"string(5) "00:00"string(8) "4100:353"string(6) "Bianco"string(7) "100:051"string(5) "00:00"string(5) "00:00"string(7) "1100:15"string(8) "6402:012"string(6) "Bianco"string(7) "402:274"string(5) "00:00"string(9) "11900:202"string(9) "11401:427"string(6) "Bianco"string(8) "2102:051"string(5) "00:00"string(7) "3300:08"string(8) "7401:423"string(6) "Bianco"string(8) "8402:104"string(5) "00:00"string(6) "Bianco"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(7) "1100:04"string(10) "121000:512"string(6) "Bianco"string(8) "5400:461"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(6) "Bianco"string(5) "00:00"string(5) "00:00"string(9) "121200:18"string(9) "11800:593"string(6) "Bianco"string(8) "6401:272"string(5) "00:00"string(6) "Bianco"string(7) "1100:04"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(7) "2200:05"string(9) "10801:102"string(6) "Bianco"string(8) "8201:166"string(5) "00:00"string(8) "3200:071"string(7) "100:261"string(6) "Bianco"string(5) "00:00"string(5) "00:00"string(7) "1100:00"string(9) "151500:26"string(10) "161301:123"string(6) "Bianco"string(8) "9500:434"string(7) "1100:00"string(7) "2200:13"string(6) "Bianco"string(7) "200:342"string(5) "00:00"string(6) "Bianco"string(7) "1100:24"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(7) "1100:04"string(8) "9700:222"string(10) "171500:582"string(6) "Bianco"string(7) "200:512"string(7) "1100:40"string(7) "1100:22"string(6) "Bianco"string(8) "3100:062"string(5) "00:00"string(5) "00:00"string(5) "00:00"string(6) "Bianco"string(5) "00:00"string(5) "00:00"string(7) "1100:22"string(8) "7500:302"string(6) "Bianco"string(5) "00:00"string(5) "00:00"string(7) "1100:06"string(6) "Bianco"string(7) "1100:00"string(5) "00:00"string(5) "00:00"
надеюсь, это то, что вы искали, я догадывалась по «xpath», который вы указали.
Я бы предложил попробовать использовать другую библиотеку для JsonPath, если в той, с которой вы работаете, есть ошибка, а сторонняя служба не сообщает об ошибке в запросе.
Вот несколько из них:
Я уверен, что есть еще. Надеюсь, это поможет.
Я решил изменить реализацию библиотеки для JsonPath: теперь я использую реализацию Skyscanner JsonPath (см. https://github.com/Skyscanner/JsonPath-PHP).
Некоторые проблемы с установкой (для меня я никогда раньше не использовал композитор …), но команда skyskanner поддержала меня (ссылка https://github.com/Skyscanner/JsonPath-PHP/issues/6) и теперь у меня есть этот код PHP ….
<?php
ini_set('display_errors', 'On');
error_reporting(E_ALL);
include "./tmp/vendor/autoload.php";
$url = 'https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs';
//#Set CURL parameters: pay attention to the PROXY config !!!!
$ch = curl_init();
curl_setopt($ch, CURLOPT_AUTOREFERER, TRUE);
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, TRUE);
curl_setopt($ch, CURLOPT_PROXY, '');
$data = curl_exec($ch);
curl_close($ch);
$jsonObject = new JsonPath\JsonObject($data);
$jsonPathExpr = "$..aziende[?(@.descrizione==\"A.S.U.I. - Trieste\")]..prontoSoccorsi[?(@.descrizione==\"Pronto Soccorso e Terapia Urgenza Trieste\")]..dipartimenti[?(@.descrizione==\"Pronto Soccorso Maggiore\")]..codiciColore[?(@.descrizione==\"Verde\")]..situazionePazienti..numeroPazientiInAttesa";
$r = $jsonObject->get($jsonPathExpr);
//print json_encode($r);
print json_encode($r[0]);
?>
в ./tmp
Я имею то, что я получаю от композитора
… это работает нормально, и таким образом я могу сделать свой запрос JSON, потенциально, не зная его точную структуру
<?php // PRINT SI JSON ORIGINAL
define("DIRPATH", dirname($_SERVER["SCRIPT_FILENAME"]) . '/');
define("WEBPATH", 'http://' . $_SERVER['SERVER_ADDR'] . dirname($_SERVER['PHP_SELF']) . '/');
//define("WEBPORT", 'http://' . $_SERVER['SERVER_ADDR'] . ':' . $_SERVER['SERVER_PORT'] . dirname($_SERVER['PHP_SELF']) . '/');
//define("imgpath", DIRPATH . 'image/');
//$png = file_get_contents('iptv.kodi.al/images/');
$jsondata = file_get_contents('https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs');
header("Content-type: application/ld+json; charset=utf-8");
$print = json_decode($jsondata);
print_r($print);
?>
<?php // PRINT ME KATEGORI
define("DIRPATH", dirname($_SERVER["SCRIPT_FILENAME"]) . '/');
define("WEBPATH", 'http://' . $_SERVER['SERVER_ADDR'] . dirname($_SERVER['PHP_SELF']) . '/');
//define("WEBPORT", 'http://' . $_SERVER['SERVER_ADDR'] . ':' . $_SERVER['SERVER_PORT'] . dirname($_SERVER['PHP_SELF']) . '/');
//define("imgpath", DIRPATH . 'image/');
//$png = file_get_contents('iptv.kodi.al/images/');
$jsondata = file_get_contents('https://servizionline.sanita.fvg.it/tempiAttesaService/tempiAttesaPs');
header("Content-type: application/ld+json; charset=utf-8");
$print = json_decode($jsondata);
//print_r($print);
$items = '';
// KETU FILLON LISTA
foreach ($print->{'aziende'} as $item) {
$items .= '
' . $item->id . '
' . $item->descrizione . '
';
};
?>
<?php echo $items; ?>