JSON Transfer of Bigint: 12000000000002539 Is Converted to 12000000000002540

JSON transfer of bigint: 12000000000002539 is converted to 12000000000002540?

The value is actually not exceeding the maximum numeric value in JavaScript (which is "only" 1.7308 or so).

However, the value is exceeding the range of "integral precision". It is not that the wrong number is sent: rather, it is that the literal 12000000000002539 can only be represented as precisely as 12000000000002540, and thus there was never the correct numeric value in JavaScript. (The range of integrals is about +/- 253.)

This is an interesting phenomena of using a double relative-precision (binary64 in IEEE-754 speak) type to store all numeric values, including integers:

12000000000002539 === 12000000000002540 // true

The maximum significant number of decimal digits that be precisely stored as a numeric value is 15 (15.95, really). In the above, there are 17 significant digits, so some of the least-significant information is silently lost. In this case, as the JavaScript parser/engine reads in the literal value.

The only safe way to handle integral numbers of this magnitude in JavaScript is to use a string literal or to break it down in another fashion (e.g. a custom numeric type or a "bigint library"). However, I recommend just using a string, as it is human readable, relatively compact (only two extra characters in JSON), and doesn't require special serialization. Since the value is just an "id" in this case, I hope that math does not need to be performed upon it :)

Happy coding.

Error occurred While try to parsing JSON String using java

Your json is wrong to parse in Java. The maximum value of Long is 9223372036854775807 in Java but in your json you are exceeding it. Json can access really really long numbers, but java won't.

Just change number types in json as String after that you are good to go. Look at the following example.

{
"read": "2015-05-07T19:30:48.165009273+05:30",
"network": {
"rx_bytes": 11124,
"rx_packets": 116,
"rx_errors": 0,
"rx_dropped": 0,
"tx_bytes": 648,
"tx_packets": 8,
"tx_errors": 0,
"tx_dropped": 0
},
"cpu_stats": {
"cpu_usage": {
"total_usage": 157158138204,
"percpu_usage": [
157158138204
],
"usage_in_kernelmode": 49530000000,
"usage_in_usermode": 58420000000
},
"system_cpu_usage": 258964110000000,
"throttling_data": {
"periods": 0,
"throttled_periods": 0,
"throttled_time": 0
}
},
"memory_stats": {
"usage": 73969664,
"max_usage": 74600448,
"stats": {
"active_anon": 73928704,
"active_file": 4096,
"cache": 86016,
"hierarchical_memory_limit": "18446744073709552000898498494949849849849849849849849849841998498498484984",
"inactive_anon": 4096,
"inactive_file": 32768,
"mapped_file": 32768,
"pgfault": 62880,
"pgmajfault": 0,
"pgpgin": 34656,
"pgpgout": 34482,
"rss": 73883648,
"rss_huge": 67108864,
"total_active_anon": 73928704,
"total_active_file": 4096,
"total_cache": 86016,
"total_inactive_anon": 4096,
"total_inactive_file": 32768,
"total_mapped_file": 32768,
"total_pgfault": 62880,
"total_pgmajfault": 0,
"total_pgpgin": 34656,
"total_pgpgout": 34482,
"total_rss": 73883648,
"total_rss_huge": 67108864,
"total_unevictable": 0,
"total_writeback": 0,
"unevictable": 0,
"writeback": 0
},
"failcnt": 0,
"limit": 2099310592
},
"blkio_stats": {
"io_service_bytes_recursive": [],
"io_serviced_recursive": [],
"io_queue_recursive": [],
"io_service_time_recursive": [],
"io_wait_time_recursive": [],
"io_merged_recursive": [],
"io_time_recursive": [],
"sectors_recursive": []
}
}

Edit: After @Jon Skeet's comment i realised, he's right about Json simple. In a different json parser you can easilly parse your json, and it will handle it as BigInteger. BigInteger has no limit.

Here's an example:

try{
String line = "{'read':'2015-05-07T19:30:48.165009273+05:30','network':{'rx_bytes':11124,'rx_packets':116,'rx_errors':0,'rx_dropped':0,'tx_bytes':648,'tx_packets':8,'tx_errors':0,'tx_dropped':0},'cpu_stats':{'cpu_usage':{'total_usage':157158138204,'percpu_usage':[157158138204],'usage_in_kernelmode':49530000000,'usage_in_usermode':58420000000},'system_cpu_usage':258964110000000,'throttling_data':{'periods':0,'throttled_periods':0,'throttled_time':0}},'memory_stats':{'usage':73969664,'max_usage':74600448,'stats':{'active_anon':73928704,'active_file':4096,'cache':86016,'hierarchical_memory_limit':18446744073709552000,'inactive_anon':4096,'inactive_file':32768,'mapped_file':32768,'pgfault':62880,'pgmajfault':0,'pgpgin':34656,'pgpgout':34482,'rss':73883648,'rss_huge':67108864,'total_active_anon':73928704,'total_active_file':4096,'total_cache':86016,'total_inactive_anon':4096,'total_inactive_file':32768,'total_mapped_file':32768,'total_pgfault':62880,'total_pgmajfault':0,'total_pgpgin':34656,'total_pgpgout':34482,'total_rss':73883648,'total_rss_huge':67108864,'total_unevictable':0,'total_writeback':0,'unevictable':0,'writeback':0},'failcnt':0,'limit':2099310592},'blkio_stats':{'io_service_bytes_recursive':[],'io_serviced_recursive':[],'io_queue_recursive':[],'io_service_time_recursive':[],'io_wait_time_recursive':[],'io_merged_recursive':[],'io_time_recursive':[],'sectors_recursive':[]}}";
line = line.replaceAll( "'", "\"" );
while( line != null ){

JsonObject asJsonObject = new JsonParser().parse( line ).getAsJsonObject().get( "network" ).getAsJsonObject();
Set<Entry<String, JsonElement>> entrySet = asJsonObject.entrySet();

for( Entry<String, JsonElement> entry : entrySet ){
System.out.println( entry.getKey() + " : " + entry.getValue() );
}
}
}
catch( Exception e ){
System.out.println( "Error occured :" + e );
}

I used gson to parse your json. Thanks @Jon Skeet.

String to Number conversion fails to give the expected result in javascript

First off, there is no binary number format in JS that gets used when you just write ones and zeros, 1110101 is just one million, one hundred ten thousand, one hundred one, and not 117 in binary.

JavaScript uses double-precision floating-point format numbers as specified in IEEE 754 and can only safely represent integers between -(2^53 - 1) and 2^53 - 1. In JS this is called Number.MAX_SAFE_INTEGER. If you look at the max int and your number side by side:

9007199254740991
11110100001000111111

It becomes quite apparent, that eleven quintillion, one hundred ten quadrillion, one hundred trillion, one billion, one hundred eleven thousand, one hundred eleven is bigger than the max int, so you are bound to have precision loss.

To get a base 10 integer from a binary number, you can pass parseInt a radix as the second parameter:

console.log(parseInt("11110100001000111111", 2))

JSON.Stringify() on big numbers alters the numeric value?

JavaScript represents numbers using IEEE-754 double-precision (64 bit) format. As I understand it this gives you 53 bits precision, or fifteen to sixteen decimal digits. Your number has more digits than JavaScript can cope with, so you end up with an approximation.

Do you need to do maths operations on this big number? Because if its just some kind of ID you can return it as a string and avoid the problem.

Working with an API in javascript which uses IDs above JS max integer

change the number into a string before parsing:

var responseData = JSON.parse(
strJson.replace(/\: (\d{17,}),/g,': "$1",')
);

note this will falsely modify any string data that contains a big number that looks like a json value, but i'd call that a worthy tradeoff compared to the deep-investment alternatives. still, it's not just a big number that hits, but (": " + theNumber +","); the only time i can imagine that happening is someone "re-tweeting" the JS-invalid API response. use a parser if you care that much about being perfect.

IntegerField value gets converted to a string for some numbers

I guess @proppy is right. Also, it clearly states in the discovery format that

A 32-bit signed integer ("integer" type, int32 format). It has a minimum value of -2,147,483,648 and
a maximum value of 2,147,483,647 (inclusive)

and

A 32-bit unsigned integer ("integer" type, uint32 format). It has a minimum value of 0 and a maximum
value of 4,294,967,295 (inclusive).

All other kinds of int/bigint/whatever values are repesented as "string" types with different formats. More info: https://developers.google.com/discovery/v1/type-format

So, 1234567890123 number cannot in fact be represented in "integer" type. It's just the dev server doesn't convert integers to strings automatically (like the production infrastructure does), and I didn't realize how big the number was while testing locally.

It turns out a team at Google is already working on making it consistent: https://code.google.com/p/googleappengine/issues/detail?id=9173

Simple Regex NOT on multidimensional JSON string

(?!\\") is a negative lookahead, which generally isn't useful at the very beginning of a regular expression. In your particular regex, it has no effect at all: the expression (?!(\\\"))(\:) means "empty string not followed by slash-quote, then a colon" which is equivalent to just trying to match a colon by itself.

I think what you were trying to accomplish is a negative lookbehind, which has a slightly different syntax in PCRE: (?<!\\"). Making this change seems to match what you want: https://regex101.com/r/xI1zI4/2



Related Topics



Leave a reply



Submit