Skip to content

Commit

Permalink
avoid reparsing numbers when serializing
Browse files Browse the repository at this point in the history
Update StringBasedNumericNode.scala
  • Loading branch information
pjfanning committed Sep 5, 2024
1 parent 6d2feae commit 995ddc0
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,8 @@ sealed class PlayJsonMapperModule(jsonConfig: JsonConfig) extends SimpleModule("
// -- Serializers.

private[jackson] class JsValueSerializer(jsonConfig: JsonConfig) extends JsonSerializer[JsValue] {
import java.math.BigInteger
import java.math.{ BigDecimal => JBigDec }

import com.fasterxml.jackson.databind.node.BigIntegerNode
import com.fasterxml.jackson.databind.node.DecimalNode

private def stripTrailingZeros(bigDec: JBigDec): JBigDec = {
val stripped = bigDec.stripTrailingZeros
if (jsonConfig.bigDecimalSerializerConfig.preserveZeroDecimal && bigDec.scale > 0 && stripped.scale <= 0) {
Expand All @@ -96,10 +92,7 @@ private[jackson] class JsValueSerializer(jsonConfig: JsonConfig) extends JsonSer
val stripped = stripTrailingZeros(v.bigDecimal)
val raw = if (shouldWritePlain) stripped.toPlainString else stripped.toString

if (raw.indexOf('E') < 0 && raw.indexOf('.') < 0)
json.writeTree(new BigIntegerNode(new BigInteger(raw)))
else
json.writeTree(new DecimalNode(new JBigDec(raw)))
json.writeTree(new StringBasedNumericNode(raw))
}

case JsString(v) => json.writeString(v)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) from 2022 The Play Framework Contributors <https://github.com/playframework>, 2011-2021 Lightbend Inc. <https://www.lightbend.com>
*/

package play.api.libs.json.jackson

import com.fasterxml.jackson.core.{ JsonGenerator, JsonParser, JsonToken }
import com.fasterxml.jackson.databind.SerializerProvider
import com.fasterxml.jackson.databind.node.NumericNode

import java.math.{ BigDecimal, BigInteger }

/**
* A numeric node that is represented as a string.
*
* For internal use only. Some methods are not implemented and will throw an exception.
*/
private[jackson] case class StringBasedNumericNode(text: String) extends NumericNode {

override def numberType = JsonParser.NumberType.BIG_DECIMAL

override def asText(): String = text

override def asToken(): JsonToken = JsonToken.VALUE_NUMBER_FLOAT

override def serialize(jgen: JsonGenerator, ctxt: SerializerProvider): Unit =
jgen.writeNumber(text)

override def numberValue: Number = throw new NotImplementedError

override def intValue: Int = throw new NotImplementedError

override def longValue: Long = throw new NotImplementedError

override def doubleValue: Double = throw new NotImplementedError

override def decimalValue: BigDecimal = throw new NotImplementedError

override def bigIntegerValue: BigInteger = throw new NotImplementedError

override def canConvertToInt: Boolean = false

override def canConvertToLong: Boolean = false
}

0 comments on commit 995ddc0

Please sign in to comment.