Closed rhdunn closed 3 weeks ago
I am in the process of porting a third-party format to Kotlin Multiplatform and came across this issue as well. Note that it is not limited to just the value 0.0
. Instead, it seems to be related to how Double.toString()
works in general.
See the following test code:
val json = Json { prettyPrint = true }
val values = listOf(0.0, 0.9e-6, 1.0e-6, 0.9e-3, 1.0e-3, 0.9e+7, 1e+7, 0.9e+21, 1e+21)
println("Json.encodeToString: ${json.encodeToString(values)}")
Executed using both Kotlin/JVM and Kotlin/Native, this code produces the following output:
Json.encodeToString: [
0.0,
9.0E-7,
1.0E-6,
9.0E-4,
0.001,
9000000.0,
1.0E7,
9.0E20,
1.0E21
]
This is the default JVM behavior that seems to be emulated by this Kotlin/Native code. For the JS target (Node.js), however, it produces the following output on my Linux machine:
Json.encodeToString: [
0,
9e-7,
0.000001,
0.0009,
0.001,
9000000,
10000000,
900000000000000000000,
1e+21
]
This seems to be the default JS behavior documented here.
Yes, because numbers on JS are represented as JS's number
type, they have a different format in the string representation. I'm not sure we can do anything meaningful here except by writing Double.toString()
logic from scratch.
For my use case I'm now allowing both integer and decimal numbers and converting the integers to Double
. In the tests, I'm checking that the deserialized value is either 0
or 0.0
.
Describe the bug When using
JsonPrimitive
with aDouble
argument to specify a decimal JSON type, the0.0
value is serialized as an integer0
value instead on the JS (IR and Legacy).Note: This breaks JSON schemas or protocols that specify decimal types (e.g. Language Server Protocol decimal type).
To Reproduce
JsonPrimitive(0.0).toString()
Expected behavior Returns
0.0
.Actual behavior Returns
0
on JS,0.0
on JVM and Native.Environment
[jsIr, browser, Firefox107.0, Windows10]
,[jsIr, node]
,[jsLegacy, browser, Firefox107.0, Windows10]
,[jsLegacy, node]