json_decode reformatting decimals in JSON based on locale - php

I'm currently working on a site that's localized in a couple of languages and I'm running into a problem where json_decode is reformatting decimals in JSON strings depending on the locale. When the locale is set to "en" the decimals remain untouched. However, in the "fr_FR" locale they get changed to "13,3" for example.
Source JSON:
{"debug":[{"id":13.3}]}
Output for "en"
Array
(
[debug] => Array
(
[0] => Array
(
[id] => 13.3
)
)
)
Output for "fr_FR"
Array
(
[debug] => Array
(
[0] => Array
(
[id] => 13,3
)
)
)
Is there any reason json_decode does this? Is there a way to prevent it?
The bug is causing problems with the Gravity Forms Wordpress plugin, but I've already isolated the problem to the json_decode function.

It looks like the issue is with how PHP handles numeric values. json_decode is simply transforming 13.3 to a float, which on output or being converted to a string is the localized "13,3". However, PHP does not deal well with localized number formats.
As per this thread, using setlocale has resolved the issue (for the most part)
setlocale(LC_NUMERIC, 'C');

Related

How are 'c' or 'r' date format working in PHP?

I've tried to format some date using 'c' or 'r' format and I ended up having weird results.
I've tried the PHP interpreter from my personal computer or using the php:latest Docker image.
Along the way, I've tried many methods and even the results of these ones surprised me.
var_dump(DateTime::createFromFormat('c', (new DateTime())->format('c'))); // false
// or
var_dump(DateTime::createFromFormat('r', (new DateTime())->format('r'))); // false
(new DateTime())->format('c') returns a string in the expected format but I thought creating a DateTime object from it would return a valid object and not false.
What's this behavior ?
Thanks for your help :)
Those format characters are unknown as per documentation, where it's also stated (emphasis mine):
$format The format that the passed in string should be in. See the formatting options below. In most cases, the same letters as for the date() can be used.
You can call DateTime::getLastErrors() to see more (though slightly confusing) details:
Array
(
[warning_count] => 0
[warnings] => Array
(
)
[error_count] => 2
[errors] => Array
(
[0] => The format separator does not match
[1] => Trailing data
)
)

Convert array to string to write to session file

How can I convert an array to a serialized string that I can write to a session file? This is being done in a command line script, not in a browser, so I can not use session_write_close().
I have tried serialize() function and that does not convert it properly (see below).
Notice: I already know I shouldn't manually write to a session file, and I should use the database for session data instead.
If I use file_get_contents() on the session file I get:
user_id|i:4;user_first_name|s:9:"FirstName";user_last_name|s:8:"LastName";user_last_login|s:10:"2016-06-03";random_data|a:4:{s:2:"ID";i:83;s:3:"URL";a:1:{i:0;s:23:"https://www.example.com";}s:4:"Date";s:10:"2016-06-08";s:4:"Year";s:4:"2016";}
I convert it to an array with some PHP and get:
Array
(
[user_id] => 1
[user_first_name] => FirstName
[user_last_name] => LastName
[user_last_login] => 2016-06-03
[random_data] => Array
(
[ID] => 83
[URL] => Array
(
[0] => https://www.example.com
)
[Date] => 2016-06-08
[Year] => 2016
)
)
Now I need to convert the array back into a string for the session file:
user_id|i:4;user_first_name|s:9:"FirstName";user_last_name|s:8:"LastName";user_last_login|s:10:"2016-06-03";random_data|a:4:{s:2:"ID";i:83;s:3:"URL";a:1:{i:0;s:23:"https://www.example.com";}s:4:"Date";s:10:"2016-06-08";s:4:"Year";s:4:"2016";}
I used Serialize() and got this (not the same as what came out of the session file):
a:12:{s:7:"user_id";i:4;s:15:"user_first_name";s:9:"FirstName";s:14:"user_last_name";s:8:"LastName";s:15:"user_last_login";s:10:"2016-06-03";s:11:"random_data";a:24:{s:2:"ID";i:83;s:3:"URL";a:1:{i:0;s:23:"https://www.example.com";}s:3:"API";N;s:4:"Date";s:10:"2016-06-08";s:4:"Year";s:4:"2016";}}
EDIT: It has to be the same format as the original string format (from file_get_contents()) because when I insert the serialize() string format it logs me out of the website.
You can use php functions serialize and unserialize to do that. By the way, the advantage of this way, that it saves type of, at least, standard php objects. For example, this code:
$o = new DateTime();
print_r(unserialize(serialize($o)));
returns DateTime Object
You can use JSON format:
json_encode(array);
For decode:
json_decode($json_string);

php json_encode

I have a symfony app that uses the json_encode and json_decode to keep a record of some prices.
The problem is that json_decode works OK in one file (I can decode the string stored in my PSQL database), but when I call it from other file json_decode returns null, I've check the file encodings (all are utf-8) the tables and database encoding(utf-8 too). So I don't know where the problem can be, tried utf8_encode() too...
Any help will be appreciated.
Thanks.
Here's the valid encoded json (It was an array encoded by php json_encode)
{"1":{"1":{"fechaInicio":"30-05-2011","precios":{"1":{"precio":"20000","abreviatura":"CLP"}},"fechaRetiro":"31-05-2011"}},"2":{"2":{"fechaInicio":"30-05-2011","precios":{"1":{"precio":"20000","abreviatura":"CLP"}},"fechaRetiro":"31-05-2011"}}}
The array:
$preciosOfertor = Array ( [unidades] => Array ( [1] => Array ( [1] => Array ( [fechaInicio] => 30-05-2011 [precios] => Array ( [1] => Array ( [precio] => 20000 [abreviatura] => CLP ) ) [fechaRetiro] => 31-05-2011 ) ) [2] => Array ( [2] => Array ( [fechaInicio] => 30-05-2011 [precios] => Array ( [1] => Array ( [precio] => 20000 [abreviatura] => CLP ) ) [fechaRetiro] => 31-05-2011 ) ) ) )
To encode it I use:
$preciosOfertor = json_encode($preciosOfertor);
Then I call
$precios = json_decode($databaseObject->getPreciosOfertor(),true);
When i use json_decode in the file that encodes the array it works, but then when I use it in other file of the project I just get NULL with var_dump().
Installed Services_JSON as suggested, but now I'm getting an empty array
The encoded json with Services_JSON is this one:
{"unidades":{"1":{"1":{"fechaInicio":"30-05-2011","precios":{"1":{"precio":"20000","abreviatura":"CLP"}},"fechaRetiro":"31-05-2011"}}}}
But when I call $json->decode() I get Array ( )
Ok people, first thank you all for the help.
I got the solution and It was all thanks to Zend Json library.
Symfony uses escaping strategies to prevent XSS attacks, SQL Injection attacks, etc. So what happened here in my case, when I called json_encode and json_decode it was inside the object that Doctrine generates to represent my object (In this case a reservation), so because it was a local call to the row data (valoresOfertor), the data from the database was not escaped thus the methods worked fine.
But then, when I tried to encode and decode the values of the row outside the reservation class, Symfony used it's escaping strategy so
"
became
&quot
So, trying different JSON libraries, I used Zend one, and saw the exception that displayed (Syntax Error:
at Zend_Json::decode('{"unidades":{"1":{"1":{"fechaInicio":"30-05-2011","precios":{"1":{"precio":"20000","abreviatura":"CLP"}},"fechaRetiro":"31-05-2011"}},"2":{"2":{"fechaInicio":"30-05-2011","precios":{"1":{"precio":"20000","abreviatura":"CLP"}},"fechaRetiro":"31-05-2011"}}}}')
in SF_ROOT_DIR/apps/saas/modules/editreserva/templates/habitacionesSuccess.php line 20 ...
So then i Added the following line:
htmlspecialchars_decode($jsonVariable);
And it worked.
I hope it helps someone if he experiments the same with symfony and json.
As far as I know, there were one or more bugs in json_encode() and json_encode() in previous versions of PHP. You could try to update PHP to the latest version or you could use an external library to encode and decode JSON. There are some, but I think PEAR JSON is the best.
it might be the UTF-8 BOM present. Try using UTF without BOM encoding. Also echo the json_last_error() to see what's the problem.
EDIT:
It IS a valid JSON
From php.net : NULL is returned if the json cannot be decoded or if the encoded data is deeper than the recursion limit.
So either you've set e recursion limit lower than the data depth (which may not seem to be the case, if you say that it does work on another page), or the json cannot be decoded.
If it works on one page and it doesn't in another, check the file encoding.
The first page may be encoded to utf-8 (the encoding of your json) but the second one might be something else (like ascii). check the bom also.Youw may need to encode the page to utf-8 without bom.
If it's a template you're dealing it, have a look at:
$sf_data->getRaw();
http://www.geeganage.com/symfony-json-made-easy/

Parsing php array in python

I'm getting a PHP array from a web page (as a string).
It looks like :
Array
(
[k1] => Array
(
[a] => Array
(
[id] => 1
[age] => 60
)
[b] => Array
(
[id] => 2
[age] => 30
)
)
[k2] => v2
)
I want to parse it in python.
Does anyone have an idea how to do this?
Thanks,
Rivka
Edit:
This is really not a json, like a few people commented.
Thanks for the comments, and I updated the question.
That's not JSON, that's just how PHP prints arrays. If you want to create JSON of the array, check out json_encode for PHP. Then use Python's JSON library (or here for py3) to read it.
If I understood you correctly, you are using print_r on array to get that output. This is a visual representation of array only, you can't really parse it. For example:
array('Array'.PHP_EOL."\t(".PHP_EOL." [0] => test".PHP_EOL."\t)")
will look exactly like
array(array('test'));
You should use some real serializing function to do what you want(json,serialize etc.);

Working with Delicious API json response

When I try to find out the total count of delicious bookmarks, Delicious returns a json file which when decoded is:
Array (
[0] => stdClass Object (
[hash] => e60558db2d649c8a1933d50f9e5b199a
[title] => ISRAEL: Thousands march in Jerusalem rally, Israel still kicking
new families out of land they've owned for 60+ years
[url] => http://english.aljazeera.net/news/middleeast/2010/03/2010362141312196.html
[total_posts] => 2
[top_tags] => Array ()
)
)
The array is a stdClass Object. How can I extract [total_count] using PHP.
P.S Since I could not figure out how to extract it, I am using strpos to find 'total_count' and then I am cutting the string from that position and then extracting integers out of it. :)
BUt it is way too long.
Solved
If you pass a second argument, true, in your json_decode, it will return a regular array as opposed to an object. You might find this easier to work with.
$array = json_decode($json, true);
If you pass a second argument, true, in your json_decode, it will return a regular array as opposed to an object. You might find this easier to work with.
$array = json_decode($json, true);
Have you tried
echo $stdClass->total_posts;
Do you mean [total_posts]? If so, you should use $delArray[0]->total_posts.
See http://us.php.net/manual/en/language.types.object.php for samples on accessing object properties.

Categories