I'm a PHP noob...
anyway - how do I get all the image links from this string? (into an array)
{ "imagedata": { "duration": 4000, "images":{ "image1":{ "url":"/images/nature/flowers/pictureKUO133529A.jpeg", "title":"", "index":"01" }, "image2":{ "url":"/images/nature/flowers/pic092533.jpg", "title":"", "index":"02" }, "image3":{ "url":"/images/nature/flowers/pic092529.jpg", "title":"", "index":"03" }, "image4":{ "url":"/images/nature/flowers/pic092531.jpg", "title":"", "index":"04" }, "image5":{ "url":"/images/nature/flowers/pic092530.jpg", "title":"", "index":"05" }, "image6":{ "url":"/images/nature/flowers/pic092534.jpg", "title":"", "index":"06" }, "image7":{ "url":"/images/nature/flowers/0112678pic092532.jpg", "title":"", "index":"07" }, "image8":{ "url":"/images/nature/flowers/0112881pic092656.jpg", "title":"", "index":"08" }, "image9":{ "url":"/images/nature/flowers/0112880pic092655.jpg", "title":"", "index":"09" } } } }
I have tried with preg_match_all() but i can't get it working....
I just want strings like /images/nature/flowers/0112880pic092655.jpg
btw I have scraped the above data from a script tag...
Thanks in advance
Well, you can use a regex for that. But as it seems to be JSON, a simple call to json_decode() might do.
Set the second parameter to TRUE if you want an array structure.
Then access it like:
print $array["imagedata"]["images"]["image1"]["url"];
Related
I understand there are other similar posts about this, I am going out of my wits end here.
I have a few files with some JSON (all valid according to online validators, eg. jsonlint) - see EDIT below.
$contents = file_get_contents(DATA_PATH.'/'.$type.'.json');
$data = json_decode($contents, true);
echo var_dump($data);
Returns NULL
If I echo $contents, I do get output.
I'm not sure what is wrong? I understand file_get_contents gets it into a string, however, how do I get it in a valid JSON? Would using fopen() be any different?
I even added the JSON to a variable but had the same outcome... I must be stupid.
Note: Most JSON I'll get will be from an API, these file-based JSONs are for testing purposes.
Thanks.
EDIT: Sample json
{
"data": [{
"id": 1,
"name": "Albania",
"alpha2code": "AL",
"alpha3code": "ALB",
"capital": "Tirana",
"flag": "https://cdn.elenasport.io/flags/svg/1",
"region": "Europe",
"subregion": "Southern Europe",
"timezones": [
"UTC+01:00"
]
},
{
"id": 3,
"name": "Algeria",
"alpha2code": "DZ",
"alpha3code": "DZA",
"capital": "Algiers",
"flag": "https://cdn.elenasport.io/flags/svg/3",
"region": "Africa",
"subregion": "Northern Africa",
"timezones": [
"UTC+01:00"
]
}]
}
Your file might have a UTF-8 BOM which is not copied when you copy-and-paste your sample JSON to a (web based) validator. It's an invisible mark at the beginning of your file.
If you run echo bin2hex(file_get_contents(DATA_PATH.'/'.$type.'.json')) your file should begin with 7b, which is a {.
If it starts with efbbbf and then a 7b, there is a BOM. Either strip it out yourself or re-save your JSON without one using a text editor like Sublime Text which allows you to configure that.
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.
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.
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']);
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 }")