Retrieve information from JSON file properly using JSONReader in PHP - php

I am trying to retrieve information from a JSON file using JSONReader (I've implemented JSONReader to my PHP configuration) and I am trying to get the information from a simple JSON file (see below) about the whole part of the array (part, where Home Lawrence Library is) and I am struggling with this.
To be honest, I don't know how to use JSONReader properly.
This is my code:
inline <?php $reader = new JSONReader();
$reader->open('http://www.example.com/news.json');
while ($reader->read()) {
switch($reader->tokenType) {
case JSONReader::ARRAY_START:
echo "Array start:\n";
break;
case JSONReader::ARRAY_END:
echo "Array end.\n";
break;
case JSONReader::VALUE:
echo " - " . $reader->value . "\n";
break;
}
}
$reader->close();
?>
It is just printing array start and array end, but does not print the value.
JSON code:
{
"markers": [
{
"homeTeam": "Lawrence Library",
"awayTeam": "LUGip",
"markerImage": "images/red.png",
"information": "Linux users group meets second Wednesday of each month.",
"fixture": "Wednesday 7pm",
"capacity": "",
"previousScore": ""
},
{
"homeTeam": "Hamilton Library",
"awayTeam": "LUGip HW SIG",
"markerImage": "images/white.png",
"information": "Linux users can meet the first Tuesday of the month to work out harward and configuration issues.",
"fixture": "Tuesday 7pm",
"capacity": "",
"tv": ""
},
{
"homeTeam": "Applebees",
"awayTeam": "After LUPip Mtg Spot",
"markerImage": "images/newcastle.png",
"information": "Some of us go there after the main LUGip meeting, drink brews, and talk.",
"fixture": "Wednesday whenever",
"capacity": "2 to 4 pints",
"tv": ""
}
] }
Link to the JSONReader documentation: https://github.com/shevron/ext-jsonreader
Btw, I am trying to parse big JSON files so please do not suggest to use json_decode or curl methods.

Related

Adding JSON to PHP file

I am trying to add a JSON script to a php file in my sites admin. My goal is to have the JSON run when the order status is change to 3 (shipped).
I am pretty sure I am going about this all wrong but I am not sure what to do yet. here is my code:
if ( ($check_status['orders_status'] != $status) && $check_status['orders_status'] == 3) { ?>
<script>
POST https://api.yotpo.com/oauth/token
{
"client_id": "### Your client_id ###",
"client_secret": "### Your client_secret ###",
"grant_type": "client_credentials"
}
POST https://api.yotpo.com/myapi/purchases
{
"validate_data": true,
"platform": "general",
"utoken": "### YOUR UTOKEN ###",
"email": "client#abc.com",
"customer_name": "bob",
"order_id": "order_1",
"order_date": "2010-10-14",
"currency_iso": "USD",
"products": {
"SKUaaa12": {
"url": "http://example_product_url1.com",
"name": "product1",
"image": "http://images2.fanpop.com/image/photos/13300000/A1.jpg",
"description": "this is the description of a product",
"price": "100",
"specs": {
"upc": "USB",
"isbn": "thingy"
},
"product_tags": "books"
}
}
}
</script>
<?php } ?>
First of all, there is nothing in my code that says hey, this is JSON besides the tag.
do I need to have the json in a sepearate json file? Or do I need to convert this script to php?
First of all, Nikita is correct that JSON does not run - it is not script. It is a standardized way to store information.
PHP has native JSON handling functions and can easily take existing objects or arrays and convert them to JSON.
<?php
$json = json_encode($my_data);
?>
<input type="hidden" name="post_data" <?php echo 'value="'.$json.'" ?> />
Then when you send this variable $json to the next page, you'll unpack it like so
$my_data = json_decode($_POST['post_data']);
This is a pure PHP implementation, though JavaScript does nice functions to stringify to/from json as well.

Iterating through this JSON string in PHP

This is my file, titled parks.JSON:
{
"state": [
{
"name": "Alabama",
"park1": "Bladon Springs State Park",
"park1Link": "http://www.stateparks.com/bladon_springs_state_park_in_alabama.html",
"park2": "Florala State Park",
"park2Link": "http://www.stateparks.com/florala_state_park_in_alabama.html"
},
{
"name": "Alaska",
"park1": "Chugach State Park",
"park1Link": "http://www.stateparks.com/chugach_state_park_in_alaska.html",
"park2": "Kachemak Bay State Park",
"park2Link": "http://www.stateparks.com/kachemak_bay_state_park_in_alaska.html"
}
]
}
And this is my php embedded in an html file to call it:
$json_url = "../data/parks.JSON";
$parksJSON = file_get_contents($json_url);
$parksData = json_decode($parksJSON, TRUE);
I am not sure how to go about iterating through my array. I, of course, will have all 50 states entered here in theory.
I have read other posts asking this and their methods don't work because my JSON format is always different from theirs it seems!
I would have thought a pretty simple loop would do it
foreach ($parksData["state"] as $state)
{
echo $state["name"];
}

PHP Json Decode code not working dailymotion

I'm using php to decode dailymotion api for related videos but my code is not working.. If i replace "list" with any other word it works perfectly.. But i have to use the word list due to dailymotion api.. Anyone who can help?
$string='{"list":[
{
"duration": 233,
"id": "x2laq9v",
"thumbnail_480_url": "http://s1.dmcdn.net/JsC-U/x480-8Xl.jpg",
"title": "Heart Touch Mashup 2015 | Hindi latest Sad Songs | Very Sad Song"
},
{
"duration": 239,
"id": "x2laq9v",
"thumbnail_480_url": "http://s1.dmcdn.net/JsC-U/x480-8Xl.jpg",
"title": "title 2"
}
]}';
$json_a=json_decode($string,true);
// array method
foreach($json_a[list] as $p)
{
echo '
duration: '.$p[duration].'
<br>title: '.$p[title].'
<br><br>';
}
You have decoded the JSON string as an associative array. You need to access the elements by giving the key as a string. Otherwise, PHP will assume it as a constant.
So, change
foreach($json_a[list] as $p)
{
echo '
duration: '.$p[duration].'
<br>title: '.$p[title].'
<br><br>';
}
to
foreach($json_a["list"] as $p)
{
echo '
duration: '.$p["duration"].'
<br>title: '.$p["title"].'
<br><br>';
}
It should work fine, then.
Try to put quotes on the array :
foreach($json_a['list'] as $p)

Convert JSON string to array WITHOUT json_decode

I am using PHP on shared server to access external site via API that is returning JSON containing 2 levels of data (Level 1: Performer & Level 2: Category array inside performer). I want to convert this to multidimensional associative array WITHOUT USING json_decode function (it uses too much memory for this usage!!!)
Example of JSON data:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
I have tried to use substr and strip the "[" and "]".
Then performed the call:
preg_match_all('/\{([^}]+)\}/', $input, $matches);
This gives me the string for each row BUT truncates after the trailing "}" of the category data.
How can I return the FULL ROW of data AS AN ARRAY using something like preg_split, preg_match_all, etc. INSTEAD of the heavy handed calls like json_decode on the overall JSON string?
Once I have the array with each row identified correctly, I CAN THEN perform json_decode on that string without overtaxing the memory on the shared server.
For those wanting more detail about json_decode usage causing error:
$aryPerformersfile[ ] = file_get_contents('https://subdomain.domain.com/dir/getresults?id=1234');
$aryPerformers = $aryPerformersfile[0];
unset($aryPerformersfile);
$mytmpvar = json_decode($aryPerformers);
print_r($mytmpvar);
exit;
If you have a limited amount of memory, you could read the data as a stream and parse the JSON one piece at a time, instead of parsing everything at once.
getresults.json:
[
{
"performerId": 99999,
"name": " Any performer name",
"category": {
"categoryId": 99,
"name": "Some category name",
"eventType": "Category Event"
},
"eventType": "Performer Event",
"url": "http://www.novalidsite.com/something/performerspage.html",
"priority": 0
},
{
"performerId": 88888,
"name": " Second performer name",
"category": {
"categoryId": 88,
"name": "Second Category name",
"eventType": "Category Event 2"
},
"eventType": "Performer Event 2",
"url": "http://www.novalidsite.com/somethingelse/performerspage2.html",
"priority": 7
}
]
PHP:
$stream = fopen('getresults.json', 'rb');
// Read one character at a time from $stream until
// $count number of $char characters is read
function readUpTo($stream, $char, $count)
{
$str = '';
$foundCount = 0;
while (!feof($stream)) {
$readChar = stream_get_contents($stream, 1);
$str .= $readChar;
if ($readChar == $char && ++$foundCount == $count)
return $str;
}
return false;
}
// Read one JSON performer object
function readOneJsonPerformer($stream)
{
if ($json = readUpTo($stream, '{', 1))
return '{' . readUpTo($stream, '}', 2);
return false;
}
while ($json = readOneJsonPerformer($stream)) {
$performer = json_decode($json);
echo 'Performer with ID ' . $performer->performerId
. ' has category ' . $performer->category->name, PHP_EOL;
}
fclose($stream);
Output:
Performer with ID 99999 has category Some category name
Performer with ID 88888 has category Second Category name
This code could of course be improved by using a buffer for faster reads, take into account that string values may themselves include { and } chars etc.
You have two options here, and neither of them include you writing your own decoder; don't over-complicate the solution with an unnecessary work-around.
1) Decrease the size of the json that is being decoded, or
2) Increase the allowed memory on your server.
The first option would require access to the json that is being created. This may or may not be possible depending on if you're the one originally creating the json. The easiest way to do this is to unset() any useless data. For example, maybe there is some debug info you won't need, so you can do unset($json_array['debug']); on the useless data.
http://php.net/manual/en/function.unset.php
The second option requires you to have access to the php.ini file on your server. You need to find the line with something like memory_limit = 128M and make the 128M part larger. Try increasing this to double the value already within the file (so it would be 256M in this case). This might not solve your problem though, since large json data could still be the core of your problem; this only provides a work-around for inefficient code.

Craft a JSONpath expression so that it retrieves only a specific value?

I have some JSON of which the following is a small sample:
{
"results": {
"div": [
{
"class": "sylEntry",
"div": [
{
"class": "sT",
"id": "sOT",
"p": "Mon 11/17, Computer work time"
},
{
"class": "des",
"id": "dOne",
"p": "All classes Siebel 0218"
}
],
"id": "sylOne"
}
]
}
}
I would like to only retrieve the "p" content for the div element with class "sT". I would like to use a loop and doing something like this:
var arrayOfResults = $.results..div.p
does not work because I only want to retrieve the p value for the div element with class "sT".
So how do I construct my JSONpath so that it will retrive the array of p elements that are contained within the divs class "sT".
Thanks!!
Concepts
JSONPath apparently has a filter syntax that allows you to insert arbitrary Javascript into an expression for the purposes of matching or filtering. It also uses # as a shortcut for the current node. Their example of combining these two things looks like this:
$..book[?(#.price<10)] // filter all
books cheapier than 10
So this is probably what you want to use here.
Solution
To test the query I had in mind, I modified the jsonpath-test-js.html file in JSONPath's repo to test your data. You can copy-paste my sample to an HTML file and just load it in a browser.
Their test suite has an array of objects with fields called o and p. o contains the original data to operate on while p contains an array of JSONPath expressions to apply to o. It loops over all these pairs and applies all the ps to their respective os, printing out the result. Not as handy as a simple REPL, but it'll do.
Here's what I came up with:
<html>
<head>
<title> JSONPath - Tests (js)</title>
<script type="text/javascript" src="http://www.json.org/json.js"></script>
<script type="text/javascript"
src="http://jsonpath.googlecode.com/svn/trunk/src/js/jsonpath.js">
</script>
</head>
<body>
<pre>
<script type="text/javascript">
var out = "", tests =
[ { "o": { "results" : { "div" : [ { "clazz": "sylEntry",
"id": "sylOne", "div": [ { "clazz": "sT", "id": "sOT",
"p": "Mon 11/17, Computer work time" }, { "clazz": "des",
"id": "dOne", "p": "All classes Siebel 0218" } ] } ] } },
"p": ["$.results..div[?(#.clazz=='sT')].p", // my suggestion expression
"$.results..div[*].p"]}, // your question's expression
];
function evaluate($, p) {
var res = eval(p);
return res != null ? res.toJSONString() : null;
}
for (var i=0; i<tests.length; i++) {
var pathes;
for (var j=0; j<tests[i].p.length; j++) {
pre = ">";
if (pathes = jsonPath(tests[i].o, tests[i].p[j], {resultType: "PATH"}))
for (var k=0; k<pathes.length; k++) {
out += pre + " " + pathes[k] +
" = " + evaluate(tests[i].o, pathes[k]) + "\n";
pre = " ";
}
}
out += "<hr/>";
}
document.write(out);
</script>
</pre>
</body>
</html>
Note that this will first print the results of my query expression and then print the results of yours, so we can compare what they produce.
Here's the output it produces:
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
$['results']['div'][0]['div'][4]['p'] = "All classes Siebel 0218"
So the correct operator in the filter expression is ==, meaning the correct expression for you is:
$.results..div[?(#.class=='sT')].p
However, I discovered one unfortunate issue (at least in the Javascript implementation of JSONPath): using the word 'class' in the above query results in this:
SyntaxError: jsonPath: Parse error: _v.class=='sT'
My only guess is that there's an eval being called somewhere to actually evaluate the JSONPath expression. class is a reserved word in Javascript, so it's causing issues. Let's try using the alternate syntax for #.class:
$.results..div[?(#.['class']=='sT')].p
Results:
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
> $['results']['div'][0]['div'][0]['p'] = "Mon 11/17, Computer work time"
$['results']['div'][0]['div'][5]['p'] = "All classes Siebel 0218"
So use the above expression and you should be good to go! The filter feature looks powerful, so it'll probably be well worth exploring its capabilities!
Instead of using hard-to-grasp, non-standard query style, you could use DefiantJS (http://defiantjs.com), which extends the global object JSON with the method "search" - with which you can query JSON structures with standardised XPath queries. This method returns the matches in an array (empty array if no matches were found).
Here is a working JSfiddle of the code below;
http://jsfiddle.net/hbi99/sy2bb/
var data = {
"results": {
"div": {
"class": "sylEntry",
"id": "sylOne",
"div": [
{
"class": "sT",
"id": "sOT",
"p": "Mon 11/17, Computer work time"
},
{
"class": "des",
"id": "dOne",
"p": "All classes Siebel 0218"
}
]
}
}
},
res = JSON.search( data, '//div[class="sT"]/p' );
console.log( res[0] );
// Mon 11/17, Computer work time
To get an idea of XPath and how it works, check out this XPath Evaluator tool:
http://defiantjs.com/#xpath_evaluator
try this
JsonPath.with(jsonResponse).param("name", "getName").get("findAll { a -> a.name == name }")

Categories