how to get the value from this json response using php - php

i need to extract the exam from this json response using php
cb({"data": [{"map": {"exam": ["e", "x", "a", "m"]}, "words": false, "o": ["exam", "exam", "exam"]}]},150)

The problem here is that the answer is wrapped in a callback function cb() which is not valid JSON. The JSON part is the parameter that is passed to this function (everything between and including {...}). So the first step is to remove this "outer function":
$json = trim($json, 'cb(),150');
$data = json_decode($json, true);
$exam = $json['data'][0]['map']['exam'];
Reference: trim, json_decode, arrays
This only works if the number at the end only consists of 1, 5 or 0. You can either add all digits to the second parameter of trim or use a combination of strripos and substr to chop off everything after }.

Related

PHP - substr() bug or invalid argument

I working at PHP Project With PHP Version 7.0.13
I was dealing with JSON lately, I have a JSON file that needs to be decode to PHP but before I decode the JSON, I need to clean some abstract string inside the file that JSON obtained inside, to clean the string using substr() to get the JSON.
when i write the code, like this:
$jsonraw = "\"{ JSON should be here, later }\"";
$cutstart = strpos($jsonraw, "{");
$cutend = strrpos($jsonraw, "\"");
$jsonclean = substr($jsonraw, $cutstart, $cutend);
echo $jsonclean;
The output is like this
{ JSON should be here, later }
But when the string is like this
$jsonraw = "\"some abstract string to remove { JSON should be here, later }\"";
The output is became like this
{ JSON should be here, later }"
As we can see there was a quote symbol " at the last of the string, I was trying to decrement the $cutend, like this $jsonclean = substr($jsonraw, $cutstart, --$cutend); and this to $cutend-1
Any help, I appreciate.
Sorry for my bad English
You can use preg_match to get the json from that string:
$string = "some abstract string to remove { JSON should be here, later }";
preg_match('/\{.*\}/', $string, $match);
var_dump($match[0]);
the result would be:
string(30) "{ JSON should be here, later }"
As the third parameter is the length of the string, you need to say that the length is the end position minus the start position...
$jsonclean = substr($jsonraw, $cutstart, $cutend-$cutstart);

Multiple patterns within regex

I have a json and I need to match all "text" keys as well as the "html" keys.
For example, the json could be like below:
[{
"layout":12,
"text":"Lorem",
"html":"<div>Ipsum</div>"
}]
Or it could be like below:
[{
"layout":12,
"settings":{
"text":"Lorem",
"atts":{
"html":"<div>Ipsum</div>"
}
}
}]
The json is not always using the same structure so I have to match the keys and get their values using preg_match_all. I have tried the following to get the value of the "text" key:
preg_match_all('|"text":"([^"]*)"|',$json,$match_txt,PREG_SET_ORDER);
The above works fine for matching a single key. When it comes to matching a second key ("html" in this case) it just doesn't work. I have tried the following:
preg_match_all('|"text|html":"([^"]*)"|',$json,$match_txt,PREG_SET_ORDER);
Can you please give me some hints why the OR operator (text|html) doesn't work? Strangely, the above (multi-pattern) regex works fine when I test it in an online tester but it doesn't work in my php files.
Fixing text|html
You should add text|html to a group, otherwise it will look for "text or html".
|"(text|html)":"([^"]*)"|
Delimiters
This won't currently work with your delimiters though as you use the pipe (|) inside of the expression. You should change your delimiters to something else, here I've used /.
/"(text|html)":"([^"]*)"/
If you still want to use the pipe as your delimiters, you should escape the pipe within the expression.
|"(text\|html)":"([^"]*)"|
If you don't want to manually escape it, preg_quote() can do it for you.
$exp = preg_quote('"(text|html)":"([^"]*)"');
preg_match_all("|{$exp}|",$json,$match_txt,PREG_SET_ORDER);
Parsing JSON
Although that regex will work, it will need additional parsing and it makes more sense to use a recursive function for this.
json_decode() will decode a JSON string into the relative data types. In the example below I've passed an additional argument true which means I will get an associative array where you would normally get an object.
Once findKeyData() is called, it will recursively call itself and work through all of the data until it finds the specified key. If not, it returns null.
function findKeyData($data, $key) {
foreach ($data as $k => $v) {
if (is_array($v)) {
$data = findKeyData($v, $key);
if (! is_null($data)) {
return $data;
}
}
if ($k == $key) {
return $v;
}
}
return null;
}
$json1 = json_decode('[{
"layout":12,
"text":"Lorem",
"html":"<div>Ipsum</div>"
}]', true);
$json2 = json_decode('[{
"layout":12,
"settings":{
"text":"Lorem",
"atts":{
"html":"<div>Ipsum</div>"
}
}
}]', true);
var_dump(findKeyData($json1, 'text')); // Lorem
var_dump(findKeyData($json1, 'html')); // <div>Ipsum</div>
var_dump(findKeyData($json2, 'text')); // Lorem
var_dump(findKeyData($json2, 'html')); // <div>Ipsum</div>
preg_match_all('/"(?:text|html)":"([^"]*)"/',$json,$match_txt,PREG_SET_ORDER);
print $match_txt[0][0]." with group 1: ".$match_txt[0][1]."\n";
print $match_txt[1][0]." with group 1: ".$match_txt[1][1]."\n";
returns:
$ php -f test.php
"text":"Lorem" with group 1: Lorem
"html":"<div>Ipsum</div>" with group 1: <div>Ipsum</div>
The enclosing parentheses are needed : (?:text|html); I couldn't get it to work on https://regex101.com without. ?: means the content of the parentheses will not be captured (i.e., not available in the results).
I also replaced the pipe (|) delimiter with forward slashes since you also have a pipe inside the regex. Another option is to escape the pipe inside the regex: |"(?:text\|html)":"([^"]*)"|.
I don't see any reason to use a regex to parse a valid json string:
array_walk_recursive(json_decode($json, true), function ($v, $k) {
if ( in_array($k, ['text', 'html']) )
echo "$k -> $v\n";
});
demo
You use the Pipe | character as delimiter, I think this will break your regexp. Does it work using another delimiter like
preg_match_all('#"text|html":"([^"]*)"#',$json,$match_txt,PREG_SET_ORDER);
?

How to get data from associative array [duplicate]

This question already has an answer here:
How to extract and access data from JSON with PHP?
(1 answer)
Closed 5 years ago.
How to write PHP for get data from this.
{"room":[{"single_room":1,"twin_room":3}]}{"total_amount":[{"amount":20899}]}{"travelernum":[{"total":1}]}
I tried like this
$BookingDetail["room"]["single_room"];
but got result like this
Illegal string offset 'room'
and
Illegal string offset 'single_room'
How to solve it.
Try this ... you need to decode the json, you get a PHP object and then you can access each element ..
<?php
$str = '{"room":[{"single_room":1,"twin_room":3}]}{"total_amount":[{"amount":20899}]}{"travelernum":[{"total":1}]}';
$json = json_decode($str);
echo "<pre>";
print_r($json);
echo "</pre>";
echo $json->room->single_room;
By the way, I think your json is invalid. You can check this out at http://jsonlint.com/
The string you are using looks like JSON but it doesn't check out as valid. See JSONLint.com... Editing it to make it valid (single line)...
{"room": [{"single_room": 1, "twin_room": 3}], "total_amount": [{"amount": 20899}], "travelernum": [{"total": 1 }]}
OR (Multi-Line)...
{
"room": [{
"single_room": 1,
"twin_room": 3
}],
"total_amount": [{
"amount": 20899
}],
"travelernum": [{
"total": 1
}]
}
If this is the format all your strings are in, you can manipulate them into valid JSON by first by using...
$original_string = '{"room":[{"single_room":1,"twin_room":3}]}{"total_amount":[{"amount":20899}]}{"travelernum":[{"total":1}]}';
$new_string = str_replace("}{", ",", $original_string); // replace }{ with ,
Once your string is in valid JSON format, converting to a PHP array because rather simple, use something like this...
$BookingDetail = json_decode($new_string, true); //true param gets assoc array
I tested all the code above and it works.See PHP json_decode() function reference for more detail on converting JSON strings to PHP Arrays.
http://php.net/manual/en/function.json-decode.php

Can't decode JSON from file in PHP

I'm having troubles with json_decode in PHP:
I have this on file:
{1: ['oi','oi'], 2: ['foo','bar']}
And this is my php code:
<?php
$string = file_get_contents("quizen.json"); // the file
$json = json_decode($string);
echo $json[1][0]
?>
But the echo returns anything, I used var_dump, and I get NULL!
What's the problem?
The issue is that your file is not valid JSON since it uses single quotes for strings and has integers as object keys:
{1: ['oi','oi'], 2: ['foo','bar']}
Also, since the JSON is an object, you should decode it to an associative array using json_decode($string, true).
According to the JSON spec:
A value can be a string in double quotes, or a number, or true or false or null, or an object or an array.
Also, the object keys need to be strings.
If you change the single quotes to double quotes and edit your PHP's decode_json call to decode to an associative array, it should work. For example:
JSON:
{"1": ["oi","oi"], "2": ["foo","bar"]}
PHP:
<?php
$string = file_get_contents("quizen.json"); // the file
$json = json_decode($string, true); // set to true for associative array
echo $json["1"][0];
?>

Can I decode JSON containing PHP code?

Is it possible to have a JSON string containing PHP Code, and to have this string decoded?
For example, this works as it should:
$array = ["page", "is-home", $_SERVER["REQUEST_URI"] == "/"];
var_export($array);
// array (
// 0 => 'page',
// 1 => 'is-home',
// 2 => false,
// )
This, does not work:
$json = '["page", "is-home", $_SERVER["REQUEST_URI"] == "/"]';
$array = json_decode($json); // returns NULL
echo json_last_error_msg(); // Syntax error
The second example will only work if $_SERVER["REQUEST_URI"] == "/" is removed from the json string.
Is there a way to parse this string using json_decode, and if not, are there alternative methods to accomplish this?
Many thanks!
UPDATE
The $_SERVER["REQUEST_URI"] == "/" has to be parsed. I am trying to extend Blade Templating so that I can implement parsed functions such as this:
#add-request('page', 'is-home', $_SERVER["REQUEST_URI"] == '/')
UPDATE #2
To try to simplify the matter, I need to turn a string into an object.
$str = '["page", "is-home", $_SERVER["REQUEST_URI"] == "/"]'; // this is obtained by parsing the top blade extension (not important how)
From the string I need the following array:
$array = ["page", "is-home", true / false ]
Keep in mind that the original string can contain theoretically any PHP object for one of the JSON values.
I think you're on the right track, but instead of trying to "simulate" a decode by putting single-quotes, why not (for your proof of concept) first ENCODE, then 'echo' / 'print' the value that it returns, and then DECODE to see what it returns.
Why don't you use json_encode() to obtain json string??
// create json string by json_encode() from array
$json = json_encode([
"page",
"is-home",
$_SERVER["REQUEST_URI"] == "/"
]);
// decode the encoded string with no error, of course ....
$array = json_decode($json);
As you can clearly see in the output, your first array does not contain any PHP at all.
$array = ["page", "is-home", $_SERVER["REQUEST_URI"] == "/"];
automatically fills $array[2] with the boolean false, not with PHP code.
So, let's assume you can't do such a calculation on the client (in fact, you can do this calculation in javascript as well). So you would have to send it to the server as a json string (properly encoded), decode it, eval it, and post the result back into the array.
$json = '["page", "is-home", "$_SERVER[\"REQUEST_URI\"] == \"/\""]';
$array = json_decode($json);
$array[2]=eval($array[2]);
But please don't do this! It is a big security hole.
Instead, feel free to ask a new question as to how you can do this calculation in javascript as well.
For your case you could do:
$is_home = $_SERVER["REQUEST_URI"] == "/";
$json = '["page", "is-home", '. $is_home .']';
$array = json_decode($json);
That's because you are using a variable in your string which is not parsed. In addition, $_SERVER["REQUEST_URI"] == "/" returns false. Boolean false will be converted to an empty string if it is concatenated to a string.
You should rewrite your code to something like this:
// Is the request URI equal to "/"?
$reqUriTest = ($_SERVER["REQUEST_URI"] == "/");
// If boolean false is converted to a string, it will become an empty string.
// So we need to explicitly use values "true" or "false".
$reqUriStr = ($reqUriTest ? "true" : "false");
// Now we can insert $reqUriStr into the JSON string.
$json = '["page", "is-home", '.$reqUriStr.']';
$array = json_decode($json);

Categories