6

I need to inject a local value to a class constructor during deserialization. For example, look at the following class.

@Serializable
class SomeClass(val local: Context, val serialized: String)

I want the field local to be skipped during serialization and substituted with some predefined local value during deserialization.

The reason behind is that I'm going to transfer models through network, but operations on these models rely on a local context which I want to inject.

Because I haven't find any standard ways to achieve it, I've decided to make use of contextual serialization. So I have written the serializer:

class ContextualInjectorSerializer<T>(private val localValue: T) : KSerializer<T> {
    override val descriptor = SerialDescriptor("ValueInjection", StructureKind.OBJECT)

    override fun deserialize(decoder: Decoder): T {
        decoder.beginStructure(descriptor).endStructure(descriptor)
        return localValue
    }

    override fun serialize(encoder: Encoder, value: T) {
        encoder.beginStructure(descriptor).endStructure(descriptor)
    }
}

And used it this way:

// Context is marked with @Serializable(with = ContextSerializer::class)

val json = Json(JsonConfiguration.Stable, SerializersModule {
     contextual(Context::class, ContextualInjectorSerializer(context))
})
// serialize/deserialize

Surprisingly, it works pretty fine on JVM. However, when I compiled it to JS and tested, I got TypeError: Cannot read property 'siteId' of undefined. Here siteId is a field of Context which I try to access.

Is there a standard way to inject local parameters? What's wrong with my trick?

0 Answers0