Skip to content

Conversation

@jakobmerrild
Copy link

The Long data type is commonly used in many applications because the largest value that can be held in an Int value is 2^31-1. See: graphql/graphql-spec#73

I'm honestly torn about whether or not output strings should be allowed 👀 . As discussed in the linked issue common clients (JavaScript) does not read JSON numbers above 2^53-1 into number without loss of precision.

Also accepting String inputs without accepting String outputs seem inconsistent.

The `Long` data type is commonly used in many applications because
the largest value that can be held in an `Int` value is `2^31-1`.
See: graphql/graphql-spec#73
@linux-foundation-easycla
Copy link

linux-foundation-easycla bot commented Dec 16, 2024

CLA Signed

The committers listed above are authorized under a signed CLA.

Copy link
Contributor

@martinbonnin martinbonnin left a comment

Choose a reason for hiding this comment

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

Thanks for looking into this.

I left a few comments mainly FYI. Feel free to use them or reject them, this repo is made so that we don't have all to agree. Just resolve the comments you reject so we can know when to merge this.

Comment on lines 51 to 52
For input both IntValue and StringValue shall be accepted so long as the StringValue is a base-10 representation of a
valid value within the range.
Copy link
Contributor

Choose a reason for hiding this comment

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

Any reason why you accept string values here? This is not allowed for Int so this feels inconsistent.

Suggested change
For input both IntValue and StringValue shall be accepted so long as the StringValue is a base-10 representation of a
valid value within the range.
Inputs should be a `number` between `-2^63` and `2^63-1`. That number must not have a fractional or exponential part. A leading `-` is added to represent negative values.

Copy link
Author

Choose a reason for hiding this comment

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

I'm really on the fence w.r.t. String. On the one hand, Javascript's number doesn't accurately represent the full range of the spec, and Javascript is one of, if not the most, used language for GraphQL. On the other hand it seems weird to allow string values, especially if they aren't allowed in both the input and output. If string values are not allowed, then all Javascript implementations of the spec will have to have special handling of the incoming JSON, assuming JSON is used for (de)serialization, to avoid issues where JSON.parse incorrectly parses the number.
E.g. https://codesandbox.io/p/devbox/lr8z8x

Copy link
Author

Choose a reason for hiding this comment

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

I know that Javascript now supports BigInt, but I don't know how widely adopted it is. And either way, JSON.parse doesn't parse a JSON number into BigInt (how could it, number can have fractional parts)

Copy link
Collaborator

Choose a reason for hiding this comment

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

I think it is clear that Long needs to support string values because JSON numbers are not guaranteed to support the range required.

Copy link
Contributor

@martinbonnin martinbonnin Nov 30, 2025

Choose a reason for hiding this comment

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

@andimarek JSON supports numbers with arbitrary precision:

JSON can contain number literals of arbitrary precision. However, it is not possible to represent all 
JSON numbers exactly in JavaScript, because JavaScript uses floating point representation which 
has a fixed precision.

Copy link
Contributor

Choose a reason for hiding this comment

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

Oerall, I think JavaScript is mostly irrelevant here? Input values are either:

  • GraphQL IntValue litteral (parameter values in executable documents): supports arbitrary precision
  • JSON number litteral (json variables in the request): supports arbitrary precision

Is the concern about programmatically provided values?

I would leave this out of the scalar specs and up to the implementations. This is not something that goes over the wire and I'm fine leaving this unspecified.

Copy link
Author

Choose a reason for hiding this comment

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

As I am reading over the guidelines again I notice the following:

Additionally, the input coercion should be liberal in what it accepts, while the result coercion should be much more restricted and never produce different JSON values for logically identical values. For example a MyLocalDate scalar could accept the literals "01-10-2022" and "01102022" as input for the first of October 2022, but the result coercion should always return one of the possible representations.

Given these are still the guidelines I propose we keep the spec such that it allows string or number for input coercion.

Copy link
Contributor

@martinbonnin martinbonnin Dec 2, 2025

Choose a reason for hiding this comment

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

I disagree with the guideline and will make a separate PR to open that discussion (edit: here). The robustness principle was a thing in the eighties but these days, it's generally considered harmful, there's even a RFC about it.

Ultimately, this is your place and we don't have to agree. Feel free to resolve this discussion.

Copy link
Author

Choose a reason for hiding this comment

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

I think the spec is better off just allowing numbers. However, I was trying to figure out why I decided to include string as acceptable input originally. I believe the following factors were part of my original decision

  1. The current guide lines as quoted above
  2. The fact that Javascript doesn't play nicely with the entire range out of the box when deserializing JSON
  3. Related to the above, and purely selfish, we currently use String to represent this data type in our own custom Scalar

Copy link
Contributor

Choose a reason for hiding this comment

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

@benjie convinced me in that comment that we need strings and we can't completely ignore JS.

JSON number is better from a wire point of view but JSON.parse() is going to lose precision and it's not like we can change that or ask users to embed their own JSON parsers. (We could but I doubt it will be well received...)

I'm now team "let's require strings in both directions", same as what @benjie is suggesting in his comment I think.

jakobmerrild and others added 3 commits November 30, 2025 14:23
Co-authored-by: Martin Bonnin <martin@mbonnin.net>
Co-authored-by: Martin Bonnin <martin@mbonnin.net>
This makes the wording more consistent and removes all references
to JSON.
There's a separate suggestion to update the guide lines to not
mention being liberal in what is accepted for inputs.
See: graphql#40
@benjie
Copy link
Member

benjie commented Dec 4, 2025

Though it makes sense to use IntValue when parsing literals, for serialization I think you should definitely use strings, at least in JSON. For example, if you use to_json on a bigint in Postgres it will output a long number, which JavaScript can then not process, causing tremendous headaches. JavaScript will NOT change this, doing so would be a breaking change which is antithetical to JavaScript's design goals, so this is something that we have to live with.

Using a numeric format when serializing to JSON would make programming languages which don't have native support for parsing arbitrarily long numbers in JSON have to use a custom JSON parser for all payloads sent using the most common HTTP encoding. That's not really viable, and will result in few people adopting Long.

Instead, I'd recommend that you require string in both directions, at least for JSON.

Note this text from the spec:

a GraphQL service could define a scalar called UUID which, while serialized as a string, conforms to RFC 4122. When querying a field of type UUID, you can then rely on the ability to parse the result with an RFC 4122 compliant parser. Another example of a potentially useful custom scalar is URL, which serializes as a string, but is guaranteed by the service to be a valid URL.

Serializing to string is perfectly valid, and is a safe fallback for basically everything. Even binary can serialize as string via base64/etc.

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