Skip to content
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

Support Big Numbers #37

Open
brimworks opened this issue Aug 25, 2016 · 6 comments
Open

Support Big Numbers #37

brimworks opened this issue Aug 25, 2016 · 6 comments
Assignees

Comments

@brimworks
Copy link

Since all numbers are represented as double, larger numbers (like longs) get truncated. For example, the output of this code...

cjson.encode(cjson.decode("9007199254740992"))```

...is not the same as the input. This is needed since I need to sometimes parse the JSON output of APIs that I do not control and that use numbers that do not fit into doubles.

A proposed fix is in this pull request:

https://github.com/mpx/lua-cjson/pull/36
@mpx
Copy link
Owner

mpx commented Aug 25, 2016

..continuing the discussion from #36 here..

@brimworks, thanks for providing the motivating example of an API that returns larger numbers as an opaque ID field. Unfortunately it shows one of the limitations of JSON for serialising data. The RFC (https://tools.ietf.org/html/rfc7159#section-6) notes it's best to stick within 64-bit floats for interoperability. However, upstream APIs exist that break this..

I'm still in favour of leaving the number field a number to avoid confusion and placing an undue burden on all developers to check for this occurrence.

However, we could optionally add a metatable to the number like: { __jsonvalue = "12345678901234567890.1234567890" }

This has several advantages:

  • The decoded number is always available as a usable number within Lua.
  • We can quickly check the parsed number length in bytes to determine if there is a risk of precision loss. Eg, more digits than guaranteed to fit within a 64-bit float.
  • Applications can choose to use the exact value when and where it is needed.

In future this __jsonvalue field could be extended to allow arbitrary JSON to be substituted during encoding for a value.

As mentioned on the pull request, if there is a need for arbitrary precision in future it should be relatively straight forward to link in support and replace the existing number encode/decode support. However, the dependency should only be added if someone has a use case that requires it.

@mpx mpx self-assigned this Aug 28, 2016
@mpx
Copy link
Owner

mpx commented Aug 28, 2016

Erk.. wasn't thinking - numbers don't have individual metatables..

Back to:

  1. Runtime option to return JSON numbers as strings for application to handle.
  • Pro: Numeric methods still work due to automatic type conversion
  • Pro: Simple
  • Con: Doesn't round-trip
  1. Runtime option to return a table with the original string value for every number. Use a metatable to describe the special type and provide methods.
  • Pro: Numeric methods still work due to the metatable.
  • Pro: Can round trip using array/object metatable solution for encoding
  • Con: Complex: table per number, requires metatable methods, slower
  1. Compile time option to support arbitrary precision library
  • Pro: Numbers can be decoded/used/encoded without loss of precision
  • Con: Requires external dependency

Despite the complexity, option 2 is probably best since the lack of reliable round-trip support is typically painful (eg, arrays vs objects).

@brimworks
Copy link
Author

What about option (4):

Add a new option that allows numbers to be transformed from string into whatever type is desired? This means consumers of CJSON can choose option (1), (2), or (3) simply by defining a transform function as they see fit.

Thanks,
-Brian

@smartynov
Copy link

smartynov commented Dec 22, 2017

Upvoting this issue, as I suffer from data distortion too. For example, Viber API uses big numbers: "message_token":5124645880214536549.

It seems that initially proposed approach (just decode as strings) is the best. Anyway, one can manipulate this string in any fashion. Hope it will be resolved.

@imolein
Copy link

imolein commented Jun 11, 2018

While learning programming I tried to solve a coding challenge, where I had to send a big number to an API and ran into this problem, because lua-requests depends on lua-cjson. I hope it will be fixed in the future :)

@frank0r
Copy link

frank0r commented Sep 22, 2021

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

5 participants