I am using json_encode to transform my php multidimensional array to output json. Normally, this function would convert all values to strings. To make sure that integers values are send to javascript as integer values, I am using the numeric check:
$json = json_encode($data, JSON_NUMERIC_CHECK);
This works fine in all but one case for my app. In the php array (which is extracted from the database), there is one field that contains very large integers. I save it to database as a VARCHAR, but unfortunately this is converted to an integer when encoding to json. The problem is that since this is a very large integer, it gets rounded and therefore does not represent the true value. How could I tackle this problem?
Do you want the large number to be transformed to an integer? Your question leads me to believe you don't. If that's the case, remove the JSON_NUMERIC_CHECK option from the call and it shouldn't change the encoding of the field.
Documentation about this (and other) constants is here.
Maybe is to late but i did hit the same problem, and stuck on PHP 5.3 on the server because of legacy code that must be run with that version. The solution that i used is dumb, but did work for me: simple add an space character at the end of the long integer that is varchar readed from the db, and before sending it to json encode with JSON_NUMERIC_CHECK.
Related
I'm doing an API call which is being outputted in JSON,
The product field is "ProductID":3468490060026049912
I convert to PHP, json_decode()
Then I output the "Product ID" = float(3.4684900600261E+18)
It gets changed to a float which is rounded, I input this figure into MYSQL and it stays as the rounded figure.
How do I convert from JSON to PHP without it rounding, I need it correct to 19 digits?
You can use the JSON_BIGINT_AS_STRING flag int he $options parameter of json_decode. You will have a string, though.
You probably don't need to store these IDs as integers; it's not like you're going to do any maths on them.
Store them as strings, and you won't have any issues with precision, no matter how many digits they are.
The only reason you'd need to store these as integers is if you're using them as your primary ID field in the database and its doing auto-increment for new records.
This is also the correct way to handle storage for phone numbers, zip codes, and other data that is formatted as a number but is actually just an arbitrary sequence.
The value is too big to be stored as an integer on 32 bit machines (the maximum is about 2*109), that's why PHP converts it to float.
On 64 bit machines PHP can be stored as integer but its value is really close to the limit (which is about 9*1018). Another ID that starts with 9 or is one digit longer doesn't fit and is converted by PHP to float.
But floating point numbers loose the least significant digits.
As a quick workaround you can pass JSON_BIGINT_AS_STRING as the fourth parameter to json_decode() but it doesn't fixes the source of the problem. You can encounter the same problem on the Javascript or the database code.
You better make "ProductID" a string everywhere. It is an identifier, anyway. You don't need to do math operations with it, just to store it and search for it.
Fixed with setting ini_set('precision',19); at the top.
A plugin in my Joomla installation stores the following data structure/encoding in the database:
a:20:{s:3:"UID";s:32:"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";s:11:"X-EXTRAINFO";s:0:"";s:8:"LOCATION";s:0:"";s:11:"allDayEvent";s:3:"off";s:7:"CONTACT";s:0:"";s:11:"DESCRIPTION";s:63:"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";s:12:"publish_down";s:9:"2015-9-23";s:10:"publish_up";s:9:"2015-9-23";s:13:"publish_down2";s:9:"2015-9-23";s:11:"publish_up2";s:9:"2015-9-23";s:7:"SUMMARY";s:17:"xxxxxxxxxxxxxxxxxx";s:3:"URL";s:0:"";s:11:"X-CREATEDBY";i:708;s:7:"DTSTART";i:1443031200;s:5:"DTEND";i:1443045599;s:5:"RRULE";a:4:{s:4:"FREQ";s:4:"none";s:5:"COUNT";i:1;s:8:"INTERVAL";s:1:"1";s:5:"BYDAY";s:24:"+1SA,+2SA,+3SA,+4SA,+5SA";}s:8:"MULTIDAY";s:1:"1";s:9:"NOENDTIME";s:1:"1";s:7:"X-COLOR";s:0:"";s:9:"LOCKEVENT";s:1:"0";}
I replaced some characters with x's to erase 'sensitive' information.
I get how the encoding works: it uses arrays(a), string(s) and integer(i) with some length, if applicable, between colons.
However, I want to know name of this encoding and I would like to know it there is some off-the-shelf php-function that parses the information, like json_decode for JSON.
The encoding appears to be 'a storable representation of a value'.
As #AbraCadaver states in the comments, the PHP function serialize converts PHP data objects to this representation. The PHP function unserialize creates a PHP value from the stored representation.
Original Question
mysql-server-6.0.10
I have this problem, I'm using the COMPRESS function to update a field with a BASE64 encoded value. The "updated" base64 string is only slightly different than the value that is currently in the database but it IS different. The only part is different is the last few bytes of the string. The problem is that mysql is seeing these values as the SAME and therefore skipping the update. It returns without error letting my program thing it did what it was told but then you go back and the data is unchagned.
For example, the first one is base64 string that was previously INSERTED to the db, the second one is what I'm trying to overwrite with:
YToxOntpOjA7YToxOntzOjE1OiJ0cmFja2luZ19udW1iZXIiO2k6MjM0MjM0MjM0MzI0MDAwO319
YToxOntpOjA7YToxOntzOjE1OiJ0cmFja2luZ19udW1iZXIiO3M6MTU6IjIzNDIzNDIzNDMyNDExMSI7fX0=
I'm running this query:
UPDATE TABLE SET fieldname=COMPRESS('YToxOntpOjA7YToxOntzOjE1OiJ0cmFja2luZ19udW1iZXIiO3M6MTU6IjIzNDIzNDIzNDMyNDExMSI7fX0=') WHERE id = 'SOMEID';
Mysql comes back with 0 rows affected.
I can reproduce this in an SQL Query window via PHPMyAdmin so I know its not a problem with code.
How can I force this to just update regardless if the strings BEGIN the same way, since it obviously inst checking the entire string? Right now my workaround is to clear the present data with one query, then run another query to update against nothing. This is inefficient though and I'm not happy with it.
First question update
I actually found out this is a result of a PHP bug with JSON_NUMERIC_CHECK!
The value was getting saved in the database properly (couldnt tell because of the compression) but when my script to go back was loading the data out of the database via JSON_ENCODE the values were getting mangled by JSON_NUMERIC_CHECK.
See the bug report I filed:
https://bugs.php.net/bug.php?id=60111
Second question update and solution
So it really turns out I was way ahead of my self on this. I was using JSON_NUMERIC_CHECK incorrectly. I was using it as a blanket solution to ensure all numeric values would be, well, numeric. The flaw in this logic is that JSON_NUMERIC_CHECK's purpose in life is to attempt to convert all numeric strings to integers, in 32-bit OS environment there is a limit to how many digits an int val can be and thus using the exponential expression as it should!
It comes down to the fact that in my system, there is a possibility of a [tracking number] could actually be an extremely long string of just numbers. JSON_NUMERIC_CHECK was doing exactly what it was suppose to do by converting this to an exponentially expressed int val.
The actual fix to this was to not use JSON_NUMERIC_CHECK and to make sure that my var types were correct where I actually needed int vals before creating the object that is later passed to the front end via JSON.
Phew, a mouthfull, but i figured if anyone else runs into this problem it might be helpful. Chao!
I'm sorry guys, nevermind, the problem is that value i'm supplying is being treated as INT instead of STRING and its over the max size of an INT so its resetting to the MAX INT and therefore being the same string.
Sometimes just thinking through it enough to post a problem on here is enough to help me figure it out :)
UPDATE:
I actually found out this is a result of a PHP bug with JSON_NUMERIC_CHECK!
The value was getting saved in the database properly (couldnt tell because of the compression) but when my script to go back was loading the data out of the database via JSON_ENCODE the values were getting mangled by JSON_NUMERIC_CHECK.
UPDATE:
I'm actually just way ahead of my self. using JSON_NUMERIC_CHECK incorrectly. My bad!
I have a php script that outputs a json-encoded object with large numbers (greater than PHP_MAX_INT) so to store those numbers internally, I have to store them as strings. However, I need them to be shown as un-quoted numbers to the client.
I've thought of several solutions, many of which haven't worked. Most of the ideas revolve around writing my own JSON encoder, which I have done already, but don't want to take the time to change all the places I have json_encode to instead say my_json_encode.
Since I have no control over the server, I cannot turn remove the JSON library. I cannot undeclare json_encode, nor can I rename it. Is there any easy way to handle all this, or is the best option to just go through each and every file and rename all the method calls?
With javascript being loosely typed, why the need to control the type in the JSON data? What are you doing with this number in javascript, and would parseInt\parseFloat not be able to make the leap from string to number on the client side?
The only option I had was to use my own json_encode method renamed to my_json_encode, and then change everywhere that called that method.
I've been on working on this for ages. I am receiving a JSON from a request to an API and unfortunately the key's of each entry is a time uuid which is in binary format. I'm trying to use json_decode() to decode the json into a PHP array. However, when I echo the string I have about 80 entries but after the decode into the array, it trims it down to about 40 entries,
I should mention that I don't need these values that are in the keys, I could just strip them off if possible using array_values() maybe?
Any advice would help Thanks!
Here's some sample data
"\u001c":{"down":"1280069835000","off":"1279893600000","on":"1279886400000","up":"1280077035000"},"=":{"down":"1280163435000","off":"1279893600000","on":"1279886400000","up":"1280167035000"}
I actually contacted the development team, and they converted the binary uuid to string format, and it worked like a charm. Looks like this sort of thing may not be possible besides manually parsing out the JSON. Thanks for your efforts all!