Skip to content

Navigation Menu

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

[Serializer] Add NumberNormalizer #59670

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

Merged
merged 1 commit into from
Feb 7, 2025
Merged

Conversation

valtzu
Copy link
Contributor

@valtzu valtzu commented Feb 1, 2025

Q A
Branch? 7.3
Bug fix? no
New feature? yes
Deprecations? no
Issues Fix #59651
License MIT

Normalize BcMath\Number to string.

A few changes in comparison to the original issue description:

  1. floats not supported at all. No point using precision math if you start with non-precise value.
  2. Number is always normalized to a string. If we wanted the int cast, it should be opt-in with some context key like cast_zero_scale_to_int – though I personally don't see a need for it.

@valtzu valtzu requested a review from dunglas as a code owner February 1, 2025 16:57
@carsonbot carsonbot added this to the 7.3 milestone Feb 1, 2025
@valtzu valtzu force-pushed the number-normalizer branch 4 times, most recently from 43e9064 to 6e56489 Compare February 2, 2025 13:35
@faizanakram99
Copy link
Contributor

faizanakram99 commented Feb 3, 2025

@valtzu Thank you for the PR.

I agree that the purpose of using BcMath\Number is precision. However, the input could very well be a float considering it can come from any source (api response, db result, etc), and while operating on floats directly is risky due to precision loss, converting them into a numeric string (or a Number object) preserves accuracy. This aligns with the goal of using BCMath in the first place.

As far normalizing into int or string, I think normalizing into string seems a sensible default but maybe we can optionally have a flag (which can be provided via context) to output as int. I am fine with numeric-string though.

@derrabus
Copy link
Member

derrabus commented Feb 3, 2025

However, the input could very well be a float considering it can come from any source (api response, db result, etc)

Regarding API responses: Unfortunately, it's a limitation of the two-step process of decoding and denormalization that we convert a JSON number to a PHP float first. If we're dealing with JSON numbers, this normalizer is probably not what we want.

Regarding DB results: In SQL, you would represent a number as DECIMAL and most database drivers would return decimal values as strings in order to maintain precision. SQLite is the sad exception here.

while operating on floats directly is risky due to precision loss, converting them into a numeric string (or a Number object) preserves accuracy.

No. The moment you cast a value to a float, you risk losing precision. Converting them to a string won't recover the precsion you lost.

I'm fine with the normalizer in its current state.

@derrabus derrabus removed the Bug label Feb 3, 2025
@faizanakram99
Copy link
Contributor

faizanakram99 commented Feb 3, 2025

Regarding API responses: Unfortunately, it's a limitation of the two-step process of decoding and denormalization that we convert a JSON number to a PHP float first. If we're dealing with JSON numbers, this normalizer is probably not what we want.

It is quite normal to use symfony serializer to convert incoming api requests into dtos, numbers are often represented using floats in api requests. Things like MapRequestPayload, etc will work ootb.

Regarding DB results: In SQL, you would represent a number as DECIMAL and most database drivers would return decimal values as strings in order to maintain precision. SQLite is the sad exception here.

Yes, pdo does it alright, so probably not an issue.

No. The moment you cast a value to a float, you risk losing precision. Converting them to a string won't recover the precsion you lost.

Well, nobody is casting a number into a float, the numbers can be float initially (say from an api request), float needs to be converted into a string or BcMath\Number to ensure that operations are done with precision, if the denormalizer can accept float too it will save the additional cast.

@valtzu valtzu force-pushed the number-normalizer branch 2 times, most recently from 95da9ee to e71ba33 Compare February 3, 2025 17:02
@valtzu
Copy link
Contributor Author

valtzu commented Feb 3, 2025

Thank you for quick reviews @derrabus & @mtarld.

I rewrote the test case and exception messages based on your comments + fixed the null case.

Copy link
Member

@dunglas dunglas left a comment

Choose a reason for hiding this comment

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

Nice work!

Copy link
Contributor

@mtarld mtarld left a comment

Choose a reason for hiding this comment

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

With minor comments.

Great work 🙂

@valtzu valtzu force-pushed the number-normalizer branch 2 times, most recently from 449dcbd to 1801c74 Compare February 4, 2025 17:04
@valtzu valtzu force-pushed the number-normalizer branch from 1801c74 to 7d3be64 Compare February 4, 2025 17:54
@nicolas-grekas
Copy link
Member

What about supporting GMP numbers also? Could be done in the same PR, even maybe same class?
To me either we handle both extensions in one class named "Number", or we go with two classes and the current name needs to change.

@valtzu valtzu force-pushed the number-normalizer branch from 7d3be64 to 22a9066 Compare February 5, 2025 18:39
@valtzu
Copy link
Contributor Author

valtzu commented Feb 5, 2025

maybe same class

Ok, done.

@valtzu valtzu force-pushed the number-normalizer branch from 22a9066 to d3e3dfe Compare February 5, 2025 18:40

/**
* @requires PHP 8.4
* @requires extension bcmath
Copy link
Contributor

Choose a reason for hiding this comment

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

This means that we need either bcmath and gmp, I think this should be separated

@fabpot
Copy link
Member

fabpot commented Feb 7, 2025

Thank you @valtzu.

@fabpot fabpot merged commit e08f9af into symfony:7.3 Feb 7, 2025
9 of 11 checks passed
nicolas-grekas added a commit that referenced this pull request Feb 10, 2025
…ension (xabbuh)

This PR was merged into the 7.3 branch.

Discussion
----------

[Serializer] separate NumberNormalizer tests per PHP extension

| Q             | A
| ------------- | ---
| Branch?       | 7.3
| Bug fix?      | no
| New feature?  | no
| Deprecations? | no
| Issues        | Fix #59670 (comment)
| License       | MIT

Commits
-------

efe1e94 separate NumberNormalizer tests per PHP extension
@fabpot fabpot mentioned this pull request May 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Serializer] (De)Normalizer for BcMath\Number class
10 participants
Morty Proxy This is a proxified and sanitized view of the page, visit original site.