Skip to content

Serialize Decimal, Fraction and NumPy scalars as Int, Float and Boolean - #281

Merged
Cito merged 1 commit into
mainfrom
fix-numeric-scalar-serialization
Oct 9, 2026
Merged

Cito merged 1 commit into
mainfrom
fix-numeric-scalar-serialization

Conversation

@Cito

@Cito Cito commented Oct 9, 2026

Copy link
Copy Markdown
Member

GraphQL-core 3.2 serialized values like Decimal, Fraction or NumPy scalars as Int and Float, because it converted them with int() and float(). That was never tested though. When the scalar coercion was streamlined for 3.3.0, explicit isinstance checks replaced the conversion, and these values started raising GraphQLError. This affected values returned by database drivers and ORMs (e.g. SQLAlchemy Numeric, Django DecimalField, SUM/AVG aggregates) and by NumPy/pandas (numpy.int64, numpy.float32, ...). Only numpy.float64 kept working, because it subclasses float.

GraphQL.js also unwraps objects via valueOf() before coercing output values. Python's numeric protocols are the equivalent, so this change stays in line with the reference implementation.

Changes to output coercion only (input coercion stays strict):

  • Int accepts numbers of non-builtin types if they represent 32-bit integers exactly. Unlike 3.2, non-integer values such as Decimal("2.5") are rejected, not truncated.
  • Float converts them with float() and rejects NaN, infinite and overflowing values. They may lose precision; use a custom scalar type to preserve it.
  • Boolean also accepts them (including numpy.bool), and now always returns a Python bool. Before, numpy.float64 values produced a numpy.bool, which json.dumps cannot serialize.
  • Builtin types like bytes or complex are still rejected.
  • The docstrings of GraphQLInt, GraphQLFloat and GraphQLBoolean mention the accepted types.

The tests use Decimal, Fraction and NumPy-like stub classes, so NumPy is not needed as a test dependency. The behavior was also checked manually with NumPy 2.5.3.

This fixes #280 - thanks for reporting!

@Cito
Cito merged commit e46bc83 into main Oct 9, 2026
19 checks passed
@codspeed

codspeed Bot commented Oct 9, 2026

Copy link
Copy Markdown

Merging this PR will not alter performance

✅ 20 untouched benchmarks


Comparing fix-numeric-scalar-serialization (174d58c) with main (bdab43b)

Open in CodSpeed

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.

GraphQLFloat should accept Python Decimal for database ORM compatibility

1 participant