Davide Giuseppe Farella
11/21/2024, 7:49 AMJsonElement
and an integration test that verifies that said model is equal to another one.
The test fails because a model as a 0.000001
in a value of the Json, while the other has 1E-5
.
I spent a ridicolous amount of time on this and I even discovered Kotlin automatically convert to scientific notation when calling toString()
(screen #1)
I've been checking JsonElement
source and I'm wondering how could I even end up with a JsonPrimitive
, that is not a string, but has the decimal representation? (screen #2) 😅ephemient
11/21/2024, 8:05 AMDavide Giuseppe Farella
11/21/2024, 8:12 AMephemient
11/21/2024, 8:17 AMDavide Giuseppe Farella
11/21/2024, 8:23 AMephemient
11/21/2024, 8:25 AMephemient
11/21/2024, 8:31 AM{ "value": 0.33333333 }, { "value": 0.3333333333 }
if you're decoding them into a
@Serializable data class Struct(val value: Float)
then those two are equal. if you're decoding them into a
@Serializable data class Struct(val value: Double)
then those two are not equalDavide Giuseppe Farella
11/21/2024, 8:37 AMDavide Giuseppe Farella
11/21/2024, 8:54 AMDavide Giuseppe Farella
11/21/2024, 8:55 AMDavide Giuseppe Farella
11/21/2024, 8:55 AMephemient
11/21/2024, 9:28 AMDavide Giuseppe Farella
11/21/2024, 9:46 AMathos
11/21/2024, 1:59 PMon the first part, kotlinx.serialization.json preserves the formatting of the original source document, because it doesn't know what type of number will want out of it. perhaps it will end up being decoded to a BigDecimal, or perhaps not.This makes sense, but then why when encoding the object to a json string, it treats the
test
JsonPrimitive field as a number instead? Wouldn't it be more appropriate to serialise it as a primitive?
My expectation is that until someone somewhere explicitly needs to try and turn the primitive into a number, that shouldn't happen, and more so if it's just to "write" that primitive into a json string.ephemient
11/21/2024, 5:15 PMAny way to keep it 1:1?
fun JsonElement.preserveLiterals(): JsonElement = when (this) {
is JsonArray -> buildJsonArray {
for (item in this@preserveLiterals) add(item.preserveLiterals())
}
is JsonObject -> buildJsonObject {
for ((key, value) in this@preserveLiterals) put(key, value.preserveLiterals())
}
JsonNull -> JsonNull
is JsonPrimitive -> if (isString) this else JsonUnquotedLiteral(content)
}
why when encoding the object to a json string, it treats the test JsonPrimitive field as a number instead?when encoding
JsonElement
picks some numeric type, and kxs guesses Long, ULong, or Double depending on the contentDavide Giuseppe Farella
11/21/2024, 5:59 PMathos
11/25/2024, 10:20 AMwhen encodingI think it would be more consistent if it didn't do that. The "type" of the field inpicks some numeric type, and kxs guesses Long, ULong, or Double depending on the contentJsonElement
JsonElement
should be handled agnostically, as a "literal", in both directions (decoding, which is already the case, and encoding). It should only be interpreted when/if someone needs to take that value outside of JsonElement
.