Ryan Rolnicki
11/17/2021, 8:53 AMjean
11/17/2021, 1:41 PMvalue
attribute as part of a json payload. That attribute can potentially be of any primitive type or null. I started with a custom serializer :
class NullableAnySerializer : KSerializer<Any?> {
override val descriptor: SerialDescriptor = // What should it be here?
override fun serialize(encoder: Encoder, value: Any?) {
when (value) {
null -> encoder.encodeNull()
is Float -> encoder.encodeFloat(value)
is Boolean -> encoder.encodeBoolean(value)
else -> throw IllegalStateException("unsupported type")
}
}
override fun deserialize(decoder: Decoder): Any? {
// What should it be here?
}
}
I’m stuck at the level of descriptor
and deserialize()
what should I use in those places?Richard Gomez
11/18/2021, 3:07 AMMap<String, Any>
? It's a legitimate use case that seems to have been dismissed outright.
Saying "use JsonObject instead" but not providing any guidance is a recipe for frustration and buggy implementations:
https://github.com/Kotlin/kotlinx.serialization/issues/296
https://github.com/Kotlin/kotlinx.serialization/issues/746
https://github.com/Kotlin/kotlinx.serialization/issues/1537
https://kotlinlang.slack.com/archives/C7A1U5PTM/p1632495920135600?thread_ts=1632392673.125200&cid=C7A1U5PTMspierce7
11/18/2021, 4:34 AMkotlinx.serialization.SerializationException: Serializer for class 'Any' is not found.
Ruben Quadros
11/20/2021, 7:06 PMBen Deming
11/23/2021, 1:02 AMkotlinx-serialization-json
.
The project:
– contains androidMain
, commonMain
, and iosMain
sourceSets
– built to a framework using the syncFramework
task created by applying the Cocoapods plugin, and run using a pod post_install hook
– already uses kotlinx-serialization-protobuf
across all source sets already without incident
Our Kotlin language version is 1.5.21.
The serialization plugin is applied in this manner:
plugins {
kotlin("multiplatform")
kotlin("native.cocoapods")
kotlin("plugin.serialization") version "1.5.21"
And the dependency on kotlinx-serialization-protobuf is defined in this manner:
val commonMain by getting {
dependsOn(designSystemMain)
dependencies {
...
implementation("org.jetbrains.kotlin:kotlin-stdlib-common")
...
implementation("org.jetbrains.kotlinx:kotlinx-serialization-protobuf:1.2.1")
implementation("org.jetbrains.kotlinx:kotlinx-serialization-json:1.3.1")
}
}
A serializable class is defined like so:
@ExperimentalSerializationApi
@Serializable
data class AuthorizerRequestInfo(
@SerialName("token")
val token: String,
@SerialName("client-id")
val clientId: String,
)
Source in iosMain attempts encodes an instance of the data class in this manner:
Json.encodeToString(
serializer = serializer(),
value = AuthorizerRequestInfo(
token = ...,
clientId = ...
)
)
The iOS framework is successfully built using the syncFramework
command, but a linker issue occurs when statically linking the framework into the application:
Showing All Messages
Ld [redacted]/[redacted].app/[redacted] normal (in target '[redacted]' from project '[redacted]')
cd
....
Undefined symbols for architecture x86_64:
"_kfun:kotlinx.serialization.json.JsonClassDiscriminator#<get-discriminator>(){}kotlin.String", referenced from:
_kfun:kotlinx.serialization.json.internal#classDiscriminator__at__kotlinx.serialization.descriptors.SerialDescriptor(kotlinx.serialization.json.Json){}kotlin.String in [redacted](result.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
We aren’t making use of class discriminator, note how ‘simple’ the AuthorizerRequestInfo
class in question is, so I’m left kind of stumped.
Interestingly, the tasks that compile our iosTest
source set & links our unit test target for iOS completes successfully – we can spawn a simulator and run a test executable with them, without incident.
Does anyone have guidance on how we can debug this further?snowe
11/23/2021, 7:32 AM@Serializable
data class ChangeOrderInput(
val oldProposal: OldProposal,
val newProposals: List<NewProposal>
)
output:
@Serializable
data class ChangeOrderUnit(
val oldProposal: SingletonStore<OldProposal>,
val newProposals: ListDataStore<NewProposal>,
) : RuleUnitData
where ChangeOrderUnit
will always be deserialized from ChangeOrderInput
, never the other way around, and where SingletonStore/ListDataStores are created just by calling oldProposal.set()
or newProposals.add()
on the stores, with the element. e.g. the only difference between the objects are that the RuleUnit object has the objects contained in stores.snowe
11/23/2021, 5:35 PMArpit Shukla
11/28/2021, 4:55 AMMap<String, Any>
to a data class using kotlinx.serialization?rocketraman
11/29/2021, 6:46 AM@Serializable
sealed class Foo<out T> {
@Serializable
data class Bar<out T>(
val value: T?,
): Foo<T>()
}
Json.encodeToString(Foo.Bar(true))
works, but if it is wrapped inside another Serializable e.g.:
@Serializable
data class Whatever(val foo: Foo<Boolean>)
Json.encodeToString(Whatever(Foo.Bar(true)))
produces the error:
Exception in thread "main" kotlinx.serialization.SerializationException: Class 'Boolean' is not registered for polymorphic serialization in the scope of 'Any'.
Mark the base class as 'sealed' or register the serializer explicitly.
Halex
11/29/2021, 12:11 PMBase
(which is sealed) and Data
that extends it, and subclasses of Data
that cannot be changed, and I have other modules where I can do anything. The comments in the code below should hopefully guide you. Data
interface should be serialized taking into account only its text property (I use ConcreteData
for deserializing). The issue is that while I can serialize arbitrary subclasses (represented by RandomData
) in the context of Data
, I cannot seem to do it in the context of Base
.
Any help would be greatly appreciated!Arpit Shukla
11/30/2021, 4:57 AMdelblanco
11/30/2021, 8:43 AM@Test
fun test() {
val voluntary = Json.decodeFromString<SerializableVersionCheckResponse?>("""
|{
| "beheerCode": "VRIJWILLIGE_UPDATE",
| "bericht": "App moet geupdate worden"
|}
""".trimMargin()
)
assertNotNull(voluntary)
assertEquals("VRIJWILLIGE_UPDATE", voluntary.beheerCode)
val mandatory = Json.decodeFromString<SerializableVersionCheckResponse?>("""
|{
| "beheerCode": "VERPLICHTE_UPDATE",
| "bericht": "Oewe telefoon is oud."
|}
""".trimMargin())
assertNotNull(mandatory)
assertEquals("VERPLICHTE_UPDATE", mandatory.beheerCode)
val upToDate = Json.decodeFromString<SerializableVersionCheckResponse?>("")
assertNull(upToDate)
}
The last decodeFromString fails with the following message:
kotlinx.serialization.json.internal.JsonDecodingException: Expected start of the object '{', but had 'EOF' instead
JSON input:
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:24)
at kotlinx.serialization.json.internal.JsonExceptionsKt.JsonDecodingException(JsonExceptions.kt:32)
at kotlinx.serialization.json.internal.JsonLexer.fail(JsonLexer.kt:479)
Rafal
12/01/2021, 1:10 PM{
"number": 100
}
or
{
"number": "none"
}
depending on some conditions, how can I parse this kind of json if I want to have number: Int?
as a result? If the json responds a String
I wan’t the number to be null
JinYong Kim
12/03/2021, 2:58 AMMichal Havryluk
12/03/2021, 10:11 AMv79
12/04/2021, 4:37 PM@Serializable
class GameState {
var playerName = "Dougie McDougal"
@Transient
var saveFileName = "save1"
suspend fun save() {
println("Saving game state $saveFileName.gs.json")
val gameStateJson = Json.encodeToString(this@GameState)
val saveFile = applicationVfs["saves/$saveFileName.gs.json"]
saveFile.write(gameStateJson.toByteArray())
}
}
The serialized output is just {}
- empty. playerName
is not being serialised. Any thoughts?mbonnin
12/07/2021, 3:09 PMJson.decodeFromStream(InputStream)
close the inputStream for me or should I wrap in use {}
?rocketraman
12/07/2021, 10:44 PMkotlin.time.Duration
somewhere?ipolyzos
12/08/2021, 2:32 PMmessage JEvent {
string eventTime = 1;
string eventType = 2;
string productId = 3;
string categoryId = 4;
string categoryCode = 5;
string brand = 6;
string price = 7;
string userId = 8;
string userSession = 9;
}
and i generate the class, but when the code compiles i get
/JEventKt.kt: (13, 5): JvmField has no effect on a private property
object JEventKt {
@kotlin.OptIn(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)
@com.google.protobuf.kotlin.ProtoDslMarker
class Dsl private constructor(
@kotlin.jvm.JvmField private val _builder: io.ipolyzos.models.Event.JEvent.Builder <------------- COMPLAINS FOR THIS LINE HERE
) {
companion object {
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _create(builder: io.ipolyzos.models.Event.JEvent.Builder): Dsl = Dsl(builder)
}
@kotlin.jvm.JvmSynthetic
@kotlin.PublishedApi
internal fun _build(): io.ipolyzos.models.Event.JEvent = _builder.build()
phldavies
12/10/2021, 12:33 PM{"eventType": "MyEventType": "event": { … /*MyEventType fields */ }
or will we need a custom serializer for this?FunkyMuse
12/12/2021, 6:54 PMribesg
12/16/2021, 4:49 PM/* In a module of a KMP library */
@Serializable
internal data class GetFileResponse(
val url: String
)
// In the same module
override suspend fun getFileUrl(fileId: FileId): String =
http.get<GetFileResponse>("$baseUrl$file/$fileId") {
useAuthentication()
}.url
/* In an iOS app using the aforementioned library */
val url = try {
fileApi.getFileUrl(fileId)
} catch(t: Throwable) {
log.error("Failed to get file url for file id $fileId: ${t.message}", t)
return null
}
/* Logs when running */
ERROR - Failed to get file url for file id blablabla: Fields [name, rating] are required for type with serial name 'whatever.whatever.internal.model.UpsertCandidateEvaluationPayload.CriteriaValue', but they were missing
kotlinx.serialization.MissingFieldException: Fields [name, rating] are required for type with serial name 'whatever.whatever.internal.model.UpsertCandidateEvaluationPayload.CriteriaValue', but they were missing
The model mentioned by the log is completely unrelated and defined in a completely different place in another dependency… wat
I just updated to 1.6.0 then 1.6.10 from 1.5.31 so maybe it’s that I don’t know. Super weird bug and not sure what to do. Is it some kind of name/id/hashcode clash or something?Mendess
12/18/2021, 1:23 PM{ "createdAt": 11112222333 }
{ "createdAt": { "seconds": 179879, "nanoseconds": 1201800000 } }
class DateTime(....)
@Serializable
class Payload(val createdAt: DateTime)
(serialization is not needed)Skolson5903
12/20/2021, 6:36 PMval json = Json { encodeDefaults = true }
val jsonString = json.encodeToString(JsonObject(jsonRow))
works fine in debug producing correct JSON. But release minified build gets this exception in the encodeToString call:
Serializer for class 'x' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
k9.k: Serializer for class 'x' is not found.
Mark the class as @Serializable or provide the serializer explicitly.
What should I change to correct this? I have proguard rules set up for explicit @Serializable data classes and they work fine. But I have no rule(s) for this "dynamic" encode use case and am not sure what "class 'x'" is so don't know what rule to try. Is it saying that it can't find the serializer for Map (class 'x' minified), even though that is the explicit type required by the JsonObject constructor?
Any help/tips are appreciated, my searches for something like this are not finding good hits 🙂 This is serialization 1.3.1 and kotlin 1.6.10.holgerbrandl
12/22/2021, 9:22 AMAyfri
12/23/2021, 8:44 PMList<Pair<String, SomeClassWithSerializer>>
(I really need a List of pair, not maps, as I have to change often key names) ?
I have this code but it gives me a compiler error :
class SnapshotListPairSerializer<K, V>(private val keySerializer: KSerializer<K>, private val valueSerializer: KSerializer<V>) :
KSerializer<SnapshotStateList<Pair<K, V>>> {
override val descriptor: SerialDescriptor = ListSerializer(PairSerializer(keySerializer, valueSerializer)).descriptor
override fun serialize(encoder: Encoder, value: SnapshotStateList<Pair<K, V>>) {
encoder.encodeSerializableValue(ListSerializer(PairSerializer(keySerializer, valueSerializer)), value as List<Pair<K, V>>)
}
override fun deserialize(decoder: Decoder): SnapshotStateList<Pair<K, V>> {
val list = mutableStateListOf<Pair<K, V>>()
val items = decoder.decodeSerializableValue(ListSerializer(PairSerializer(keySerializer, valueSerializer)))
list.addAll(items)
return list
}
}
PS :
class SnapshotStateList<T> : MutableList<T>
Error in threadThiago
12/27/2021, 9:23 PMaltavir
12/29/2021, 9:18 AMReceiver class kotlinx.serialization.json.internal.PolymorphismValidator does not define or inherit an implementation of the resolved method 'abstract void polymorphicDefaultDeserializer(kotlin.reflect.KClass, kotlin.jvm.functions.Function1)' of interface kotlinx.serialization.modules.SerializersModuleCollector.
java.lang.AbstractMethodError: Receiver class kotlinx.serialization.json.internal.PolymorphismValidator does not define or inherit an implementation of the resolved method 'abstract void polymorphicDefaultDeserializer(kotlin.reflect.KClass, kotlin.jvm.functions.Function1)' of interface kotlinx.serialization.modules.SerializersModuleCollector.
Does anybody know what could cause this?Sam Garfinkel
12/30/2021, 7:38 PMKotlin.serialization
library support serialization of references? I’d like to serialize a graph.