Skip to content

avoid reparsing numbers when serializing#1074

Merged
mkurz merged 3 commits intoplayframework:mainfrom
pjfanning:faster-number-serialization
Jul 9, 2025
Merged

avoid reparsing numbers when serializing#1074
mkurz merged 3 commits intoplayframework:mainfrom
pjfanning:faster-number-serialization

Conversation

@pjfanning
Copy link
Contributor

@pjfanning pjfanning commented Sep 5, 2024

Alternative to #1073

This change avoids creating NumericNodes and parsing strings to numbers which ultimately have to be turned back to strings to write them.

I've had to leave the BigIntegerNode usage in there. Removing it breaks some tests. I've debugged and it is down to how writeNumber(String) is implemented in jackson-databind TokenBuffer. We would need to change this class in jackson-databind to fix this (and that is not likely to happen as it will probably cause other issues). Basically, writeNumber(String) is assumed to be a non-integer in TokenBuffer.

@pjfanning pjfanning force-pushed the faster-number-serialization branch from 61f53e8 to 995ddc0 Compare September 5, 2024 03:22
@pjfanning pjfanning marked this pull request as draft September 5, 2024 03:27
@pjfanning pjfanning force-pushed the faster-number-serialization branch from 995ddc0 to c399caf Compare September 5, 2024 03:53
@pjfanning pjfanning marked this pull request as ready for review September 5, 2024 03:57
@pjfanning pjfanning force-pushed the faster-number-serialization branch 2 times, most recently from b46b958 to d97f4dd Compare September 5, 2024 04:55
@cchantep
Copy link
Member

Unit test required

@pjfanning
Copy link
Contributor Author

Unit test required

@cchantep I think the existing tests do a good job of testing this code change.

@pjfanning pjfanning mentioned this pull request Sep 15, 2024
5 tasks
@pjfanning pjfanning force-pushed the faster-number-serialization branch from ccdfc2e to 41444b1 Compare September 15, 2024 14:49
json.writeTree(new DecimalNode(new JBigDec(raw)))
json match {
case _: TokenBuffer =>
json.writeTree(new BigIntegerNode(new BigInteger(raw)))
Copy link
Contributor Author

Choose a reason for hiding this comment

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

I have a change in jackson 2.18 which means this line can be changed to something that avoids the BigInteger parsing.

Copy link
Member

Choose a reason for hiding this comment

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

@pjfanning I merged the test (#1077) and also the main branch is on Jackson 2.19.1 now thanks to your pull request. Can you please now update this line with what you mentioned (as we are now on Jackson 2.18+)? thanks!

java.math.BigDecimal.valueOf(Double.MaxValue).add(java.math.BigDecimal.valueOf(1)).toString,
java.math.BigDecimal.valueOf(Double.MinValue).add(java.math.BigDecimal.valueOf(-1)).toString
)
numStrings.map { numString =>
Copy link
Member

Choose a reason for hiding this comment

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

same

Copy link
Contributor Author

Choose a reason for hiding this comment

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

some of the numbers are serialized with mathematically equivalent values but not exactly the same text represeenation - examples include numbers with + signs (which are not necessarily included in the serialized text)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

fails with this when forced to check the strings are equal as opposed to the numbers are equal

[info]   + Serialize JsNumbers with integers correctly (14 ms)
[error]   x Serialize JsNumbers with decimal points correctly (10 ms)
[error]    '3.4028235E+38' != '3.4028235E38' (JsonSpec.scala:513)
[error]   x Serialize JsNumbers with e notation correctly (10 ms)
[error]    '1.23456789012345679012345679E+999' != '1.23456789012345679012345679e999' (JsonSpec.scala:526)

This also happens with #1077 which has these tests but not the main source change

"1.23456789012345679012345679e-999",
"-1.23456789012345679012345679e-999"
)
numStrings.map { numString =>
Copy link
Member

Choose a reason for hiding this comment

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

same

@pjfanning pjfanning force-pushed the faster-number-serialization branch from b62bfb5 to bfa15b2 Compare March 19, 2025 13:17
@mkurz mkurz force-pushed the faster-number-serialization branch from bfa15b2 to e6d7170 Compare July 9, 2025 22:27
@pjfanning
Copy link
Contributor Author

@mkurz I can make a small adjustment in this PR because newer jackson releases have a new method that I added so this PR can use it

Update StringBasedNumericNode.scala

rework

Update JacksonJson.scala

add containsEOrDot

requested changes to containsEOrDot

remove StringBasedNumericNode

imports

remove new function

add test

add int serialization test

Update JsonSpec.scala

Update JsonSpec.scala
@mkurz
Copy link
Member

mkurz commented Jul 9, 2025

@mkurz I can make a small adjustment in this PR because newer jackson releases have a new method that I added so this PR can use it

haha, I just commented in the code ;) yes please go ahead

(I guess it will be

            case tb: TokenBuffer =>
              tb.writeNumber(raw, true)

because I was looking at your fork already ;)
)

@pjfanning pjfanning force-pushed the faster-number-serialization branch from e6d7170 to 9c00caf Compare July 9, 2025 22:35
@pjfanning
Copy link
Contributor Author

@mkurz I can make a small adjustment in this PR because newer jackson releases have a new method that I added so this PR can use it

haha, I just commented in the code ;) yes please go ahead

(I guess it will be

            case tb: TokenBuffer =>
              tb.writeNumber(raw, true)

because I was looking at your fork already ;) )

I pushed that change.

@mkurz mkurz merged commit 6aa8534 into playframework:main Jul 9, 2025
14 checks passed
@mkurz
Copy link
Member

mkurz commented Jul 9, 2025

@pjfanning Looking at your fork, do you also want to add PRs for the rest?

  • optional support for Jackson's fast decimal parser
  • StreamWriteConstraints

?

@pjfanning pjfanning deleted the faster-number-serialization branch July 10, 2025 00:02
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.

3 participants