diff --git a/bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/JsonBsonEncoder.kt b/bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/JsonBsonEncoder.kt index 085bbac6a5..2ab20488d8 100644 --- a/bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/JsonBsonEncoder.kt +++ b/bson-kotlinx/src/main/kotlin/org/bson/codecs/kotlinx/JsonBsonEncoder.kt @@ -25,6 +25,7 @@ import kotlinx.serialization.json.JsonEncoder import kotlinx.serialization.json.JsonNull import kotlinx.serialization.json.JsonObject import kotlinx.serialization.json.JsonPrimitive +import kotlinx.serialization.json.double import kotlinx.serialization.modules.SerializersModule import org.bson.BsonWriter import org.bson.codecs.kotlinx.utils.BsonCodecUtils.toJsonNamingStrategy @@ -98,12 +99,12 @@ internal class JsonBsonEncoder( primitive.isString -> encodeString(content) content == "true" || content == "false" -> encodeBoolean(content.toBooleanStrict()) else -> { - val decimal = BigDecimal(content).stripTrailingZeros() + val decimal = BigDecimal(content) when { - decimal.scale() > 0 -> { + isFloatingLiteral(content, decimal) -> { val abs = decimal.abs() if ((decimal.signum() == 0 || abs >= DOUBLE_MIN_VALUE) && abs <= DOUBLE_MAX_VALUE) { - encodeDouble(decimal.toDouble()) + encodeDouble(primitive.double) } else { writer.writeDecimal128(Decimal128(decimal)) } @@ -116,6 +117,9 @@ internal class JsonBsonEncoder( } } + private fun isFloatingLiteral(content: String, decimal: BigDecimal): Boolean = + content.contains('.') || decimal.scale() > 0 + private fun encodeJsonObject(obj: JsonObject) { writer.writeStartDocument() obj.forEach { k, v -> diff --git a/bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt b/bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt index c4c3246891..da20c4af02 100644 --- a/bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt +++ b/bson-kotlinx/src/test/kotlin/org/bson/codecs/kotlinx/KotlinSerializerCodecTest.kt @@ -231,21 +231,24 @@ class KotlinSerializerCodecTest { fun testJsonPrimitiveNumberEncoding(): Stream> { return Stream.of( """{"value": 0}""" to """{"value": 0}""", - """{"value": 0}""" to """{"value": 0.0}""", + """{"value": 0.0}""" to """{"value": 0.0}""", """{"value": 1.1}""" to """{"value": 1.1E0}""", - """{"value": 11}""" to """{"value": 1.1E1}""", - """{"value": 110}""" to """{"value": 1.1E2}""", - """{"value": 1100}""" to """{"value": 1.1E3}""", + """{"value": 11.0}""" to """{"value": 1.1E1}""", + """{"value": 110.0}""" to """{"value": 1.1E2}""", + """{"value": 1100.0}""" to """{"value": 1.1E3}""", """{"value": 0.1}""" to """{"value": 1E-1}""", """{"value": 0.01}""" to """{"value": 1E-2}""", """{"value": 0.001}""" to """{"value": 1E-3}""", """{"value": -1.1}""" to """{"value": -1.1E0}""", - """{"value": -11}""" to """{"value": -1.1E1}""", - """{"value": -110}""" to """{"value": -1.1E2}""", - """{"value": -1100}""" to """{"value": -1.1E3}""", + """{"value": -11.0}""" to """{"value": -1.1E1}""", + """{"value": -110.0}""" to """{"value": -1.1E2}""", + """{"value": -1100.0}""" to """{"value": -1.1E3}""", """{"value": -0.1}""" to """{"value": -1E-1}""", """{"value": -0.01}""" to """{"value": -1E-2}""", """{"value": -0.001}""" to """{"value": -1E-3}""", + """{"value": -0.0}""" to """{"value": -0.0}""", + """{"value": 3.0}""" to """{"value": 3.0}""", + """{"value": 1.0E20}""" to """{"value": 1.0E20}""", """{"value": 9223372036854775807}""" to """{"value": 9223372036854775807}""", """{"value": {"${'$'}numberDecimal": "9223372036854775808"}}""" to """{"value": 9223372036854775808}""", """{"value": -9223372036854775808}""" to """{"value": -9223372036854775808}""",