I have a strange serialization problem which I do ...
# serialization
m
I have a strange serialization problem which I do not really understand. I have some data class
AerodromeCollection
which is marked as beeing @Serializable. Now I want to add some method to easily save that as a JSON file. My first attempt was:
Copy code
fun AerodromeCollection.exportAsJson(jsonFilePath: Path, fileSystem: FileSystem) {
    fileSystem.write(jsonFilePath) {
        writeUtf8(jsonFormat.encodeToString(this))
    }
}
This compiles and runs but leads to this strange exception:
Copy code
kotlinx.serialization.SerializationException: Serializer for subclass 'RealBufferedSink' is not found in the polymorphic scope of 'BufferedSink'.
More Details inside thread.
Here is a longer stack trace.
Copy code
kotlinx.serialization.SerializationException: Serializer for subclass 'RealBufferedSink' is not found in the polymorphic scope of 'BufferedSink'.
Check if class with serial name 'RealBufferedSink' exists and serializer is registered in a corresponding SerializersModule.
To be registered automatically, class 'RealBufferedSink' has to be '@Serializable', and the base class 'BufferedSink' has to be sealed and '@Serializable'.
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:102)
	at kotlinx.serialization.internal.AbstractPolymorphicSerializerKt.throwSubtypeNotRegistered(AbstractPolymorphicSerializer.kt:114)
	at kotlinx.serialization.PolymorphicSerializerKt.findPolymorphicSerializer(PolymorphicSerializer.kt:109)
	at kotlinx.serialization.json.internal.StreamingJsonEncoder.encodeSerializableValue(StreamingJsonEncoder.kt:231)
	at kotlinx.serialization.json.internal.JsonStreamsKt.encodeByWriter(JsonStreams.kt:31)
	at kotlinx.serialization.json.Json.encodeToString(Json.kt:81)
	at de.mpmediasoft.aipbrowserww.fr.AerodromeCollection.exportAsJson(AerodromeCollectionManager.kt:80)
	at de.mpmediasoft.aipbrowserww.fr.internal.AerodromeCollectionManagerImpl.purgeAndReLoadAllData(AerodromeCollectionManagerImpl.kt:109)
However, when I just rewrite the function as
Copy code
fun exportAsJson(aerodromeCollection: AerodromeCollection, jsonFilePath: Path, fileSystem: FileSystem) {
    fileSystem.write(jsonFilePath) {
        writeUtf8(jsonFormat.encodeToString(aerodromeCollection))
    }
}
where I explicitly pass the instance of the class as a parameter, then this code works without problem and exports an instance of AerodromeCollection. Somehow the system does not like extension functions. The same problem appears when I move the extension function into the class definition as a member function. Can anybody explain me what’s going on here? This may be related to inlining because the line number of the last call from my code is wrong.
Copy code
AerodromeCollectionManager.kt:80
That file does not even have that many lines.
a
I presume that
this
refers to something else within the
write() { }
context Try replacing
Copy code
writeUtf8(jsonFormat.encodeToString(this))
with
Copy code
writeUtf8(jsonFormat.encodeToString(this@exportAsJson))
🙏 1
👍 1
m
@Adam S You are my hero. That way it works indeed.
The code was indeed called inside an apply block. Something like
Copy code
val aerodromeCollection = getAerodromeCollection().apply { exportAsGeoJson(geoJsonLocationsFilePath, fileSystem) }
and when the inner part is inlined, the
this
becomes ambiguous. At least that is my interpretation of this ugly trap.
g
It's not ambiguous in the sense that it's predictable, it's the "closest" this. That's the general risk with apply/run/extensions and why I tend to avoid them.