Convert JSON string to array WITHOUT json_decode - php

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.

Related

Convert newline in JSON and print in textarea using PHP

I already did my research first, but some topics didn't solve my issue and some quite different from what issue I have. I have a JSON that didn't print out the entire data and as upon checking the culprit is the newline when it was a value (it is my first time knowing it, my bad).
<?php
$jsn = <<<_JSON
{
"name": "Editorial",
"links": "default",
"data": [
{
"Status": "Pending",
"Tags": "Documentation",
"Info": "all documentation to be ready by Friday"
},
{
"Status": "Published",
"Tags": "Pros and Cons Limits",
"Info": "documentations about-Realtime\n-Speed per sec\n-API Limit"
}
]
}
_JSON;
$data = json_decode($jsn, true);
$output= $data['links'];
echo $output;
It will not print any output as the \n was there. So I was planning to do in the future, if they tried to use a newline, I will just temporary change the \n to other characters and decode it back. And that's where I'm having a hard time.
As testing it wasn't working for me.. Converting it back and show in textarea.
$txt = "Documentations about%2Realtime%2Speed per sec%2API Limit";
$value = str_replace("%2", '\n', $txt);
$textArea = '<textarea rows="4">'.nl2br($value).'</textarea>';
echo $textarea;
//output
//documentations about\nRealtime\nSpeed per sec\nAPI Limit
If anyone can help me in your spare time, I really appreciate it.. Thanks in advance.

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"];
}

It is possible to set fields which i want to get in overpass api&

For example. I want to get coordinates of all node buildings in bbox.
PHP
$queryBuildings="[out:json];node['building']({$y1},{$x1},{$y2},{$x2});out;";
$data = file_get_contents("http://overpass-api.de/api/interpreter?data={$queryBuildings}")
One element from result:
{
"type": "node",
"id": 29537155,
"lat": 54.6744568,
"lon": -2.1421066,
"tags": {
"building": "house",
"description": "Abandoned (2007). Associate with lead mine workings above it?",
"name": "Flushiemere House"
}
}
I want to get only lon and lat fields it's possible?
You can use skeleton print mode (out skel) which omits all tags, thus being slightly shorter. So your request should become: [out:json];node['building']({$y1},{$x1},{$y2},{$x2});out skel;
Currently csv output mode ([out:csv]) is the only mode where you can select the fields to be shown.
<?php
$data = '{
"type": "node",
"id": 29537155,
"lat": 54.6744568,
"lon": -2.1421066,
"tags": {
"building": "house",
"description": "Abandoned (2007). Associate with lead mine workings above it?",
"name": "Flushiemere House"
}
}';
$test = json_decode($data);
var_dump($test->lon);
First use json_decode to parse the response body:
$parsed_data = json_decode($data);
Then you can access the various fields like so:
$lat = $parsed_data->lat;
$lon = $parsed_data->lon;

how to get top article based on number of like in mediawiki

I'm relatively new to mediawiki and has just started last week.
Anyone can point me to the correct direction of getting the top article (based on number of likes) in mediawiki? I've already implemented the fblikebutton extension on every article and managed to retrieve the number of likes for each article.
Code that I used to check the number of likes in each article on different URLS
$query_for_fql = "SELECT like_count FROM link_stat WHERE url = '".$full_url."'";
$fqlURL = "https://api.facebook.com/method/fql.query?format=json&query=" . urlencode($query_for_fql);
$response = file_get_contents($fqlURL);
$json_data = json_decode($response);
$fb_like_count = $json_data[0]->like_count;
echo 'Facebook Like:'.$fb_like_count .'<br/>';
eg:
example.com/wiki/index.php?title=ABC (1 like)
example.com/wiki/index.php?title=XYZ (2 likes)
I tried this but this is not working
$highest = 0;
while($highest < $fb_like_count)
{
if($fb_like_count > $highest) //if loop at first
{
$highest = $fb_like_count;
echo "highest value is " . $highest . '<br/>';
}
}
I want to retrieve the content in example.com/wiki/index.php?title=XYZ and display in the "Top Article Page". What should I do next after retrieving the number of likes for each article on each url. The extensions I found for top articles are based on the number of views. But I want to classify the top article based on number of likes.
Thanks a million for helping!
As I said in my comment to you question, FQL is deprecated, and the https://api.facebook.com/method/fql.query endpoint as well.
If you want something future-proof, then you should switch to the /?ids={url1},{url2},... endpoint. You can use this one to generate the comma-separated list of URLs inn the forehand, and then retrieve all the shares in one request, for example
GET /?ids=http://www.techcrunch.com,http://www.google.com
returns
{
"http://www.techcrunch.com": {
"og_object": {
"id": "433841427570",
"title": "TechCrunch",
"type": "website",
"updated_time": "2015-05-27T21:31:39+0000",
"url": "http://techcrunch.com/"
},
"share": {
"comment_count": 0,
"share_count": 20914
},
"id": "http://www.techcrunch.com"
},
"http://www.google.com": {
"og_object": {
"id": "381702034999",
"description": "Search the world's information, including webpages, images, videos and more. Google has many special features to help you find exactly what you're looking for.",
"title": "Google",
"type": "website",
"updated_time": "2015-05-28T07:10:18+0000",
"url": "http://www.google.com/"
},
"share": {
"comment_count": 2,
"share_count": 12340803
},
"id": "http://www.google.com"
}
}
The sorting issue you have is not related to the Facebook API, but PHP.
See
https://developers.facebook.com/docs/graph-api/reference/v2.3/url
Sort JSON object in PHP by a key value
How to sort JSON objects by a certain key's value

Extracting things I want out of an array?

I had a yaml file that I needed parsed into an array and I got that done. Now this array is huge. I only want a couple values...
X1, Y1, X2, Y2, owner, that's all I would like. If I can get them to be spit out into arrays nicely it would mean the world to me. (The owner must be the owner related to those X1, y1, x2, y2 values...
(They are are all related to each other) There are many x1,y1 in the array but they all come under headings... etc I don't know how to get them all...
Here is a look at what the array spits out... (Shortened because of filesize limit)
http://pastebin.com/PyH18mZv
Any help would be appreciated.
To Parse YAML you can use various available PHP parsers. i parsed your YAML by using Online YAML Parser and output the string in JSON. At The end required array values can be accessed by decoding the JSON.
*
please note i cut the string short just for example purpose
*
$arr='{
"Residences": {
"WorkArea": {"BlackList": {"Type": "BLACKLIST", "ItemList": []},
"EnterMessage": "Welcome %player to %residence, owned by %owner.",
"Areas": {
"main": {
"Y1": 217,
"X1": -6301,
"X2": -6306,
"Y2": 205,
"Z1": 3001,
"Z2": 2981
}
},
"Permissions": {"Owner": "cal9897","World": "VivaWorld"}
},
"caylyn55": {
"BlackList": {
"Type": "BLACKLIST",
"ItemList": []
},
"EnterMessage": "Welcome %player to %residence, owned by %owner.",
"StoredMoney": 0,
"IgnoreList": {
"Type": "IGNORELIST",
"ItemList": []
},
"LeaveMessage": "Now leaving %residence.",
"Subzones": {},
"Areas": {
"main": {
"Y1": 67,
"X1": 1220,
"X2": 1210,
"Y2": 64,
"Z1": 369,
"Z2": 360
}
},
"Permissions": {
"Owner": "caylyn55",
"PlayerFlags": {},
"GroupFlags": {},
"World": "VivaWorld"
}
}
},
"Version": 1,
"Seed": 1337068141
}';
Decode JSON
$a= json_decode($arr,true);
First Area Value get through
$a['Residences']['WorkArea']['Areas']['main']['Y1'];
and Second Area value
$a['Residences']['caylyn55']['Areas']['main']['Y1'];
if ['WorkArea'] AND ['caylyn55'] dynamic you can use this code
$b=array_values($a);
foreach($b as $values)
{
if(is_array($values)) {
foreach(array_keys($values) as $c){
echo $a['Residences'][$c]['Areas']['main']['Y1'];
}
}
}
You just need to add the complete reference to the data you're trying to ouput.
Example: echo $data['Residences']['WorkArea']['Permissions']['Owner'];
Something like this
$extracted = array_map(function ($residence) {
$r = $residence['Areas']['main'];
$r['owner'] = $residence['Permissions']['Owner'];
return $r;
}, $data['Residences']);

Categories