power-media / prado3

Automatically exported from code.google.com/p/prado3
Other
0 stars 0 forks source link

JSON float encoding depends on current locale #379

Closed GoogleCodeExporter closed 8 years ago

GoogleCodeExporter commented 8 years ago
The way the TJSON class encodes/renders float values depends on the current 
locale/language on the server, which might lead to buggy behaviour if the 
locale is not US-english, as JSON parsers - and especially JavaScript itself - 
expects numberic values to be encoded using US notation. 

The solution to the problem is to force the TJSON class to always use the 
required format, regardless of the current locale on the server, which might 
have for ex. a different decimal separator then "." and might use thousand 
separators. The lines

            case 'double':
            case 'float':
                return (float) $var;

around line 144 in TJSON.php must be replaced with

            case 'double':
            case 'float':
                return strpos($s = sprintf('%F',$var),'.')!==false ? ( strpos(strtolower($s),'e')===false ? rtrim(rtrim($s,'0'),'.') : $s ) : $s;

This will change the minimum requirements of the TJSON class to PHP 4.3.10 and 
PHP 5.0.3 or later (because the %F format specifier is only available since 
those versions), but since Prado's minimum requirement is already PHP 5.3, this 
shouldn't pose a problem. 

It will also change the maximum precision used to render the float values to 
only 6 digits, which I didn't found an easy solution to circumvent using with. 
(A format string like "%1.15F" doesn't work as that will change the precision 
of the number and mess up its value even when no rounding would be needed.)

So maybe the only truly clean solution would be to use a full-blown numeric 
formatter, like PEAR NumberFormatter and call that with hardcoded separators. 
The other - somewhat simpler, but very "nasty" - solution could be to simply 
temporarily change locales for the duration of the float->string conversion 
(but not for the entire duration of JSON encoding, because that could interfere 
with interface-based iterators and array accesses).

Original issue reported on code.google.com by google...@pcforum.hu on 14 Jan 2012 at 12:05

GoogleCodeExporter commented 8 years ago
Confirmed. Fortunately TJSON is used only when json_encode() is not available, 
and that seems to act correctly. By the way prado trunk's minimum php version 
is actually 5.2, and json_encode() should be enabled by default since that 
version, even if it was broken for utf8 up to 5.2.7.
Your proposed patch look ok but changes two behaviours:
 - the first you noticed is the 6-decimals limit;
 - the second is that it transforms 'E notation' in a plain float number;

I've attached a small testcase adding another possible solution.. let me know 
your thoughts about it

Original comment by ctrlal...@gmail.com on 14 Jan 2012 at 11:15

Attachments:

GoogleCodeExporter commented 8 years ago
Since i did not receive any feedback, i've committed the patch as r3095. As 
previously noticed, since prado 3.2 requires php 5.2, TJSON should not be 
needed anymore, but it's provided just for backwards compatibility.

Original comment by ctrlal...@gmail.com on 25 Jan 2012 at 8:35

GoogleCodeExporter commented 8 years ago
The TJsonService is still explicitly instantiating the TJSON class and using 
it's encode() method. I'm not sure whether this is neccessary or 
TJavaScript::jsonEncode() could do the same job there (which in turn would call 
json_encode() if available), but in its current implementation is surely 
effected by this bug.

Original comment by google...@pcforum.hu on 25 Jan 2012 at 8:51

GoogleCodeExporter commented 8 years ago
I've committed r3097 that makes TJsonService use TJavaScript::jsonEncode().

Original comment by ctrlal...@gmail.com on 25 Jan 2012 at 10:09