-
Notifications
You must be signed in to change notification settings - Fork 63
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Erroneously rounds long integer numbers #26
Comments
I'm afraid this is a limitation of JavaScript itself. The number type only had 53 bits of precision total. Try to simply type the number in a node repl or the browser console and you'll see the echoed back value is the same thing jsonparse gives you. I would recommend storing the key as a string (maybe hex encoded to save space) if you wish to keep all the digits exactly. |
I am aware of those limitations in JavaScript. The problem is I am reading this data from the 3-rd party API Citrix to be precise. And this is how they give it to users. Would you be able to track the scenario when a sequence on numbers is longer than JavaScript can correctly parse as a Int and parse that sequence as a string? |
It is possible to check the number after parsing and if it's greater than the highest possible 53-bit integer, I could return a string or something, but that would break for people expecting a number. There are many cases where an imprecise number is better than a precise string. Do you feel confident enough to add the check to the number parser? We could maybe add it as a flag so that you could opt-in to the new behavior? The full list of characters would need to be recorded like is done for strings and then released if the number is used, or used if the number is dropped. |
Actually, it's probably a good idea to buffer the number and then use Once the new number parser is in, it would be trivial to store the string in case the parsed version is above the 53-bit threshold. |
We use JSONStream library that relies on this parser. There are many cases where it just uses a number. However in this particular case these long Int IDs are critical for the business functionality. The workaround I had was to omit the JSONStream all together, collect the data in the buffer, then use JSONbig.parse() to parse long int's; but then I run into performance issues and timeouts because instead of streaming the data I am waiting for it. To answer you question, for the purposes of our project I could fork this repo and add your workaround. I would appreciate if you could point where and how this fix should be done. Thank you for being so response, highly appreciate it |
So the basic idea is to accumulate the characters in the number as a string. You can re-use the same property string parsing uses https://github.com/creationix/jsonparse/blob/master/jsonparse.js#L176 You don't need to worry about utf-8 decoding in the number code, all the digits are in the ascii 7-bit range. Then at all the lines that emit NUMBER tokens (look like |
The |
Thank you, I will give it a try |
This fragment https://github.com/creationix/jsonparse/blob/master/jsonparse.js#L183-L307 can be replaced by this } else if (this.tState === NUMBER1 || this.tState == NUMBER2 || this.tState === NUMBER3) {
n = buffer[i];
switch (n) {
case 0x30: // 0
case 0x31: // 1
case 0x32: // 2
case 0x33: // 3
case 0x34: // 4
case 0x35: // 5
case 0x36: // 6
case 0x37: // 7
case 0x38: // 8
case 0x39: // 9
case 0x2e: // .
case 0x65: // e
case 0x45: // E
case 0x2b: // +
case 0x2d: // -
this.magnatude += String.fromCharCode(n);
this.tState = NUMBER3;
break;
default:
this.tState = START;
if (this.negative) {
this.magnatude = '-' + this.magnatude;
}
this.onToken(NUMBER, parseFloat(this.magnatude));
this.magnatude = undefined;
i--;
break;
}
} without loosing any existing functionality. Is that what you had in mind when you talked about parseFloat? |
This is close, great work. Just a couple suggestions:
You should send a pull request with the proposed changes and my suggested fixes. That way I can discuss inline and once it's good I can merge the PR and you'll get credit for the change and be listed as a collaborator in the repo. |
On point #1 |
I understand that this issue can be closed after 044b268 |
The problem is still presenting if use a negative big int number like -9223372036854775808. There is a pull request for it case #38 |
SO that
{"organizerKey": 7161093205057351174} becomes {"organizerKey": 7161093205057352000}
The text was updated successfully, but these errors were encountered: