Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unreliable serialization in output string (kotlinx date time types) #1626

Closed
master-bytes-krafter opened this issue Aug 7, 2021 · 5 comments

Comments

@master-bytes-krafter
Copy link

Describe the bug
When I try to serialize an instance of this object with kotlinx serialization, the resulting string is inconsistent, sometimes (very rarely) it outputs test0 and test1 fields in the output, but more often than not those fields are not in the result as if they were null ?

Also while debugging these two fields are considered optional (elementsOptionality field) in the generated serializer class, so is id field but this is expected

To Reproduce
Simply deserialize this class

@Serializable data class TestX( val id: String? = null, val code: Int, val reason: String, val message: String?, val test0: LocalDateTime = LocalDateTime(2020, 5, 20, 17, 0, 0) ) { val test1 = Clock.System.now() }

and then
val jsonString = Json.encodeToString(test)

Expected behavior

Environment

  • Kotlin version: 1.5.22
  • Library version: 1.2.2, datetime version: 0.2.1
  • Kotlin platforms: JVM
  • Maven 3
@master-bytes-krafter
Copy link
Author

I think i found the issue after reading serialization docs, it appears that this is default behaviour for default fields. However this feature does not make sense for every type of default field.
I leave it shortly open for a possible suggestion from the team on how to make some fields serialized even if they have default values

@master-bytes-krafter
Copy link
Author

For now as a workaround i initialize these fields in the init block,

@nataliefl
Copy link

nataliefl commented Aug 9, 2021

Had this issue when trying to assign a default long value and it seemed to randomly disappear. Initializing via the constructor works fine but only if i remove the default value as well.

@shanshin
Copy link
Contributor

shanshin commented Aug 9, 2021

Hi!
By default property with a default value is not serialized, you may change this behavior by configuring Json format like this

// file or class property
val json = Json { encodeDefaults = true }
...
// somewhere in function
val jsonString = json.encodeToString(test)

Please note that the encodeDefaults setting will affect all properties in the class. The ability to change behavior individually for each property will be added in this PR (see issue ).

Also keep in mind that if the default value is calculated, then the property is serialized only if its actual value is different from that calculated at the time of checking during serialization. That is, if the default value depends on the time, then if enough time has passed between the creation of the object and the serialization, then the property will be serialized.
For example this code

@Serializable
data class ExampleEvaluated(val l: Long = System.currentTimeMillis())

fun main() {
    println(Json.encodeToString(ExampleEvaluated()))  // if (instance.l != System.currentTimeMillis() ) serializeL()
    println(Json.encodeToString(ExampleEvaluated()))  // same
}

will unpredictably print an empty object or an object with an l field.

@master-bytes-krafter
Copy link
Author

Ok all good for me, thank you

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

No branches or pull requests

3 participants