Skip to content

fix: removes string type for large numbers as it's the wrong level of abstraction #4588

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

Open
wants to merge 1 commit into
base: gh-pages
Choose a base branch
from

Conversation

baywet
Copy link
Contributor

@baywet baywet commented May 15, 2025

rationale #4585 (comment)

Copy link
Member

@handrews handrews left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JSON does not provide for reliably transmitting integers outside of the range [-(253)+1, (253)-1], and does not provide any guarantee at all for reliably transmitting fixed point decimal. All of these need to continue to allow strings, otherwise interoperability is impossible.

@baywet
Copy link
Contributor Author

baywet commented May 15, 2025

@karenetheridge let me know if that rationale is enough for you and I can close this PR

@karenetheridge
Copy link
Member

@handrews I don't see anything in https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf about restrictions for valid number ranges.

JSON itself is just text. A number can be of any length. How a particular architecture chooses to represent that internally is up to it. Obviously a "native" number has size limitations, and different languages have different options for dealing with that. e.g. Rust has the BigInt type which can represent numbers larger than its native int32, int64 etc. An implementation can choose to represent its numbers internally however it likes; if it encodes to JSON that encoder would need to know how to handle any custom types, but this is no different from needing to understand how to encode/decode objects from a custom representation if there isn't a native object type in that language, etc.

Remember that the document model we're using is at a layer of abstraction above the implementation itself. As long as the implementation is consistent and clear about how it represents the data types, and can encode/decode to JSON (or other interoperable data formats like YAML or CSV) consistently, then from the OpenAPI/JSON Schema perspective we're all good.

Copy link
Member

@karenetheridge karenetheridge left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

thanks @baywet!

@handrews
Copy link
Member

handrews commented May 15, 2025

@karenetheridge the interoperability limits are documented in RFC8259 §6 (emphasis added):

This specification allows implementations to set limits on the range and precision of numbers accepted. Since software that implements IEEE 754 binary64 (double precision) numbers [IEEE754] is generally available and widely used, good interoperability can be achieved by implementations that expect no more precision or range than these provide, in the sense that implementations will approximate JSON numbers within the expected precision. A JSON number such as 1E400 or 3.141592653589793238462643383279 may indicate potential interoperability problems, since it suggests that the software that created it expects receiving software to have greater capabilities for numeric magnitude and precision than is widely available.

Note that when such software is used, numbers that are integers and are in the range [-(2**53)+1, (2**53)-1] are interoperable in the sense that implementations will agree exactly on their numeric values.

@handrews
Copy link
Member

I'd also like to point out that we've been telling people to encode numbers as strings for better interoperability for at least as long as I've been around the project, and yanking that now seems likely to be confusing and frustrating for anyone who followed our advice. Which is advice you can find around the internet, particularly in the context of financial work where numeric interpretation interoperability is of critical importance.

Copy link
Contributor

@ralfhandl ralfhandl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

JavaScript-based implementations parse JSON numbers into binary64 numbers in memory, which cannot represent all values of int64 or decimal128 numbers.

Which is why these "long" numbers are represented as JSON strings.

This fact is documented here for the corresponding formats.

I would be fine with removing "number" as a "base type" because interoperable senders will always use strings on the wire.

Removing "string" would be confusing for consumers of OpenAPI descriptions because they will see these formats used as for example

monetaryAmount:
  type: string
  format: decimal

@ralfhandl
Copy link
Contributor

Maybe we should rename the field/column "JSON Data Type" to "JSON representation".

As @karenetheridge pointed out JSON is a textual format for representing and exchanging data, and accepted practice for representing large numbers in JSON without loss of precision is to use JSON strings.

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

Successfully merging this pull request may close these issues.

4 participants