This does not work:
$jsonDecode = json_decode($jsonData, TRUE);
However if I copy the string from $jsonData and put it inside the decode function manually it does work.
This works:
$jsonDecode = json_decode('{"id":"0","bid":"918","url":"http:\/\/www.google.com","md5":"6361fbfbee69f444c394f3d2fa062f79","time":"2014-06-02 14:20:21"}', TRUE);
I did output $jsonData copied it and put in like above in the decode function. Then it worked. However if I put $jsonData directly in the decode function it does not.
var_dump($jsonData) shows:
string(144) "{"id":"0","bid":"918","url":"http:\/\/www.google.com","md5":"6361fbfbee69f444c394f3d2fa062f79","time":"2014-06-02 14:20:21"}"
The $jsonData comes from a encrypted $_GET variable. To encrypt it I use this:
$key = "SOME KEY";
$iv_size = mcrypt_get_iv_size(MCRYPT_BLOWFISH, MCRYPT_MODE_ECB);
$iv = mcrypt_create_iv($iv_size, MCRYPT_RAND);
$enc = mcrypt_encrypt(MCRYPT_BLOWFISH, $key, $data, MCRYPT_MODE_ECB, $iv);
$iv = rawurlencode(base64_encode($iv));
$enc = rawurlencode(base64_encode($enc));
//To Decrypt
$iv = base64_decode(rawurldecode($_GET['i']));
$enc = base64_decode(rawurldecode($_GET['e']));
$data = mcrypt_decrypt(MCRYPT_BLOWFISH, $key, $enc, MCRYPT_MODE_ECB, $iv);
some time there is issue of html entities, for example \" it will represent like this \", so you must need to parse the html entites to real text, that you can do using
html_entity_decode()
method of php.
$jsonData = stripslashes(html_entity_decode($jsonData));
$k=json_decode($jsonData,true);
print_r($k);
You have to use preg_replace for avoiding the null results from json_decode
here is the example code
$json_string = stripslashes(html_entity_decode($json_string));
$bookingdata = json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $json_string), true );
Most likely you need to strip off the padding from your decrypted data. There are 124 visible characters in your string but var_dump reports 144. Which means 20 characters of padding needs to be removed (a series of "\0" bytes at the end of your string).
Probably that's 4 "\0" bytes at the end of a block + an empty 16-bytes block (to mark the end of the data).
How are you currently decrypting/encrypting your string?
Edit:
You need to add this to trim the zero bytes at the end of the string:
$jsonData = rtrim($jsonData, "\0");
Judging from the other comments, you could use,
$jsonDecode = json_decode(trim($jsonData), TRUE);
While moving on php 7.1 I encountered with json_decode error number 4 (json syntex error). None of the above solution on this page worked for me.
After doing some more searching i found solution at https://stackoverflow.com/a/15423899/1545384 and its working for me.
//Remove UTF8 Bom
function remove_utf8_bom($text)
{
$bom = pack('H*','EFBBBF');
$text = preg_replace("/^$bom/", '', $text);
return $text;
}
Be sure to set header to JSON
header('Content-type: application/json;');
str_replace("\t", " ", str_replace("\n", " ", $string))
because json_decode does not work with special characters. And no error will be displayed. Make sure you remove tab spaces and new lines.
Depending on the source you get your data, you might need also:
stripslashes(html_entity_decode($string))
Works for me:
<?php
$sql = <<<EOT
SELECT *
FROM `students`;
EOT;
$string = '{ "query" : "' . str_replace("\t", " ", str_replace("\n", " ", $sql)).'" }';
print_r(json_decode($string));
?>
output:
stdClass Object
(
[query] => SELECT * FROM `students`;
)
I had problem that json_decode did not work, solution was to change string encoding to utf-8. This is important in case you have non-latin characters.
Interestingly mcrypt_decrypt seem to add control characters other than \0 at the end of the resulting text because of its padding algorithm. Therefore instead of rtrim($jsonData, "\0")
it is recommended to use
preg_replace( "/\p{Cc}*$/u", "", $data)
on the result $data of mcrypt_decrypt. json_decode will work if all trailing control characters are removed. Pl refer to the comment by Peter Bailey at http://php.net/manual/en/function.mdecrypt-generic.php .
USE THIS CODE
<?php
$json = preg_replace('/[[:cntrl:]]/', '', $json_data);
$json_array = json_decode($json, true);
echo json_last_error();
echo json_last_error_msg();
print_r($json_array);
?>
Make sure your JSON is actually valid. For some reason I was convinced that this was valid JSON:
{ type: "block" }
While it is not. Point being, make sure to validate your string with a linter if you find json_decode not te be working.
Try the JSON validator.
The problem in my case was it used ' not ", so I had to replace it to make it working.
In notepad+ I changed encoding of json file on: "UTF-8 without BOM".
JSON started to work
TL;DR Be sure that your JSON not containing comments :)
I've taken a JSON structure from API reference and tested request using Postman. I've just copy-pasted the JSON and didn't pay attention that there was a comment inside it:
...
"payMethod": {
"type": "PBL" //or "CARD_TOKEN", "INSTALLMENTS"
},
...
Of course after deletion the comment json_decode() started working like a charm :)
Use following function:
If JSON_ERROR_UTF8 occurred :
$encoded = json_encode( utf_convert( $responseForJS ) );
Below function is used to encode Array data recursively
/* Use it for json_encode some corrupt UTF-8 chars
* useful for = malformed utf-8 characters possibly incorrectly encoded by json_encode
*/
function utf_convert( $mixed ) {
if (is_array($mixed)) {
foreach ($mixed as $key => $value) {
$mixed[$key] = utf8ize($value);
}
} elseif (is_string($mixed)) {
return mb_convert_encoding($mixed, "UTF-8", "UTF-8");
}
return $mixed;
}
Maybe it helps someone, check in your json string if you have any NULL values, json_decode will not work if a NULL is present as a value.
This super basic function may help you. I made the NULL in an array just in case I need to add more stuff in the future.
function jsonValueFix($json){
$json = str_replace( array('NULL'),'""',$json );
return $json;
}
I just used json_decode twice and it worked for me
$response = json_decode($apiResponse, true);
$response = json_decode($response, true);
Related
in Facebook validation documentation
Please note that we generate the signature using an escaped unicode
version of the payload, with lowercase hex digits. If you just
calculate against the decoded bytes, you will end up with a different
signature. For example, the string äöå should be escaped to
\u00e4\u00f6\u00e5.
I'm trying to make a unittest for the validation that I have, but I don't seem to be able to produce the signutre because I can't escape the payload. I've tried
mb_convert_encoding($payload, 'unicode')
But this encodes all the payload, and not just the needed string, as Facebook does.
My full code:
// on the unittest
$content = file_get_contents(__DIR__.'/../Responses/whatsapp_webhook.json');
// trim whitespace at the end of the file
$content = trim($content);
$secret = config('externals.meta.config.app_secret');
$signature = hash_hmac(
'sha256',
mb_convert_encoding($content, 'unicode'),
$secret
);
$response = $this->postJson(
route('whatsapp.webhook.message'),
json_decode($content, true),
[
'CONTENT_TYPE' => 'text/plain',
'X-Hub-Signature-256' => $signature,
]
);
$response->assertOk();
// on the request validation
/**
* #var string $signature
*/
$signature = $request->header('X-Hub-Signature-256');
if (!$signature) {
abort(Response::HTTP_FORBIDDEN);
}
$signature = Str::after($signature, '=');
$secret = config('externals.meta.config.app_secret');
/**
* #var string $content
*/
$content = $request->getContent();
$payloadSignature = hash_hmac(
'sha256',
$content,
$secret
);
if ($payloadSignature !== $signature) {
abort(Response::HTTP_FORBIDDEN);
}
For one, mb_convert_encoding($payload, 'unicode') converts the input to UTF-16BE, not UTF-8. You would want mb_convert_encoding($payload, 'UTF-8').
For two, using mb_convert_encoding() without specifying the source encoding causes the function to assume that the input is using the system's default encoding, which is frequently incorrect and will cause your data to be mangled. You would want mb_convert_encoding($payload, 'UTF-8', $source_encoding). [Also, you cannot reliably detect string encoding, you need to know what it is.]
For three, mb_convert_encoding() is entirely the wrong function to use to apply the desired escape sequences to the data. [and good lord are the google results for "php escape UTF-8" awful]
Unfortunately, PHP doesn't have a UTF-8 escape function that isn't baked into another function, but it's not terribly difficult to write in userland.
function utf8_escape($input) {
$output = '';
for( $i=0,$l=mb_strlen($input); $i<$l; ++$i ) {
$cur = mb_substr($input, $i, 1);
if( strlen($cur) === 1 ) {
$output .= $cur;
} else {
$output .= sprintf('\\u%04x', mb_ord($cur));
}
}
return $output;
}
$in = "asdf äöå";
var_dump(
utf8_escape($in),
);
Output:
string(23) "asdf \u00e4\u00f6\u00e5"
Instead of trying to re-assemble the payload from the already decoded JSON, you should take the data directly as you received it.
Facebook sends Content-Type: application/json, which means PHP will not populate $_POST to begin with - but you can read the entire request body using file_get_contents('php://input').
Try and calculate the signature based on that, that should work without having to deal with any hassles of encoding & escaping.
I'm trying to convert a combined string into a ASCII Byte Array to pass it into a server as an http header. Been trying numerous ways like unpack, splitting strings and doing a loop to convert each. But the server I am passing the converted string still ignores it. Not so much of a support from the API I'm using so maybe anyone here can help if I'm doing anything wrong.
$billerId = '9999986379225246';
$authToken = '16dfe8d7-889b-4380-925f-9c2c6ea4d930';
$auth = $billerId . ':' . $authToken;
//this results in error
$auth_key_byte_array = unpack("H*",$auth);
//this also results in error
$auth_key_byte_array = hash_hmac("sha256", $auth, false);
//even tried a loop function
function create_byte_array($string){
$array = array();
foreach(str_split($string) as $char){
array_push($array, sprintf("%02X", ord($char)));
}
return implode('', $array);
}
$auth_key_byte_array = create_byte_array($auth);
I have some file called main.config which has:
{"name":"wtf","image":"main.PNG","desc":"This is about this that and that.","tags":{"php","js","html"}}
Now in php I am reading this file and getting its content like this:
$string = "";
$handle = fopen("main.config", "r");
while(!feof($handle)){
$string .= fgets($handle);
}
fclose($handle);
And now I have been trying to decode this but it always return either null or string with additional "" around.
"{"name":"wtf","image":"main.PNG","desc":"This is about this that and that.","tags":{"php","js","html"}}"
This is everything I tried:
json_decode( preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $string), true );
json_decode(preg_replace('/\s+/', '',$string), true);
json_decode(preg_replace('/\x{FEFF}/u', '', $string), true);
json_decode(str_replace('"', '"', $string));
utf8_encode($string);
stripslashes($string);
trim($string);
html_entity_decode($string);
json_decode(print_r($string, true), true);
But nothing seems to work, is it because I used some different file type or what could it be?
It was just an invalid json formatted string.
Change to:
{"name":"wtf","image":"main.PNG","desc":"This is about this that and that.","tags":["php","js","html"]}
You can also read the content with less code using:
json_decode(file_get_contents('main.config', true);
If you want to validate json format you can use this site also: jsonlint.com
I wanted to replace en/us with es/es:
<?php
$str = array('url'=>'www.domain.com\/data\/en\/us\/data.gif');
$json = json_encode($str);
$str = str_replace('en\/us', 'es\/es', $json);
echo $str;
You need to 'double escape' the backslash, like so:
<?php
$str = array('url'=>'www.domain.com/data/en/us/data.gif');
$json = json_encode($str);
$str = str_replace('en\\/us', 'es\\/es', $json);
echo $str;
See http://php.net/manual/en/language.types.string.php (section 'Single quoted').
Would be easier to escape the string BEFORE feeding it to json_encode, but I'm assuming this is a test case and the data you want to replace in is already JSON.
JSON is a useful format for moving data between systems. Converting data to JSON and then trying to manipulate it without parsing it first is almost always a terrible (overly complicated and error prone) idea.
Do the replacement before you convert it to JSON.
<?php
function replace_country($value) {
echo $value;
echo "\n";
return str_replace('en\/us', 'es\/es', $value);
}
$str = array('url'=>'www.domain.com\/data\/en\/us\/data.gif');
$str = array_map("replace_country", $str);
$json = json_encode($str);
echo $json;
Try this
$str = array('url'=>'www.domain.com\/data\/en\/us\/data.gif');
$str['url']=str_replace('en\/us', 'es\/es', $str['url']);
$json = json_encode($str);
It produce out put as
It will work for you.
Im trying to encrypt data through a custom function i created... (based on base64)
The code works but to a degree... it gives random results (sometimes work and sometimes doesn't).
<?php
set_time_limit(0);
class encryptor{
function encrypt($data){
$all = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!?#,.&*()$; ";
$chars = str_split($all, 1); // Split $all to array of single characters
$text_chars = str_split($data, 1); // Split $data to array of single characters
// Create array of unique results based on the characters from $all
foreach($chars as $char){
$array[$char] = md5(uniqid(rand(), true));
}
// Replace the input text with the results from $array
foreach($text_chars as $text_char){
$data = str_replace($text_char,$array[$text_char], $data);
}
// Encode and compress $array as $solution
$solution = gzcompress(base64_encode(json_encode($array)),9);
// Return the encoded solution + Breaker + encoded and compressed input text
return $solution."BREAKHERE".gzcompress(base64_encode($data),9);
}
function decrypt($data){
// Break the encrypted code to two parts
$exploded = explode('BREAKHERE', $data);
// Decoding the contents
$contents = base64_decode(gzuncompress($exploded[1]));
// Decoding solution ($array)
$solves = json_decode(base64_decode(gzuncompress($exploded[0])),true);
$fliped = array_flip($solves);
// Replace the encrypted data with the solution
foreach($solves as $solve){
$contents = str_replace($solve,$fliped[$solve], $contents);
}
return($contents); // Return decoded data
}
}
$text = "11 1";
$enc = new encryptor();
$encrypted = $enc->encrypt($text);
$decrypted = $enc->decrypt($encrypted);
echo $decrypted;
?>
Since its just for fun, this change appears to make it work:
// Replace the input text with the results from $array
$encrypted = '';
foreach($text_chars as $text_char){
//$data = str_replace($text_char,$array[$text_char], $data);
$encrypted .= $array[$text_char];
}
Running str_replace in the loop results in substitutions of data that have been previously substituted.
Aside from that, to make transport of the encrypted data easier, I'd change:
return $solution."BREAKHERE".gzcompress(base64_encode($data),9);
to:
return base64_encode($solution."BREAKHERE".gzcompress($data,9);
and then make the appropriate changes in the decryptor. The compress data can have null characters and non-printable characters so if you base64 encode the entire result you can pass it around more easily.