Please I need help with deserializing LinkedHashMa...
# ktor
m
Please I need help with deserializing LinkedHashMap objects. As you can see from the code, the "users" object being returned in the call.respond() function raises an error:
Copy code
kotlinx.serialization.SerializationException: Class 'LinkedHashMap' is not registered for polymorphic serialization in the scope of 'Map'. Mark the base class as 'sealed' or register the serializer explicitly.
I'd appreciate any help on how to fix this.
a
Can you share the code as text of the route's handler and the
UserSerializer
class?
m
The UserSerializer:
Copy code
@Serializable
data class UserSerializer(
    val email: String,
    val handle: String,
    val password: String,
    val dateCreated: String,
    val dateModified: String
)
Route handler (not sure if this what you mean):
Copy code
fun Application.configureRouting() {
    routing {
        static("/static") {
            resources("static")
        }

        get("") {
            call.respondFile(File("src/main/resources/openapi/swagger/index.html"))
        }

        get("/documentation.yaml") {
            call.respondFile(File("src/main/resources/openapi/documentation.yaml"))
        }

        authRouting()
        adminRouting()
        userRouting()
    }
}
a
Unfortunately, I cannot reproduce your problem with the following code:
Copy code
fun main() {
    Database.connect("jdbc:h2:mem:test;DB_CLOSE_DELAY=-1", driver = "org.h2.Driver")

    transaction {
        addLogger(StdOutSqlLogger)

        SchemaUtils.create(Users)

        Users.insert {
            it[name] = "test"
        }
    }

    embeddedServer(Netty, port = 7080) {
        install(ContentNegotiation) {
            json()
        }
        routing {
            get {
                val users = transaction {
                    val res = Users.selectAll()
                    res.map {
                        UserSerializer(it[Users.name])
                    }
                }

                call.respond(status = HttpStatusCode.Accepted, mapOf("data" to users))
            }
        }
    }.start(wait = true)
}

object Users : IntIdTable()
{
    val name = varchar("name", 100)
}

@Serializable
data class UserSerializer(
    val email: String,
)
m
do you mean it works on your end?
a
Yes
m
I've tried moving the install function that installs ContentNegotiation to the Application.module() extension function that is being passed to the embeddedServer function, but no luck still.
Is this the point where I restart my intelli j IDE or something?
a
I don't think that will help. Can you share your project?
m
Yeah, it doesn't. Tried severally. You can find here: https://github.com/believemanasseh/webo-server
One thing I've noticed is that the ktor serialization library doesn't support a lot of data types (e.g blob)
a
I think the problem is that values of the responded map have different types. I suggest defining a class instead of using a map to respond with its object.
m
Do you mean defining a data class to replace the map response object?
Also, what happens when I want to define a data type not supported by kotlin serialization library? Example, peep the displayPicture and bannerPicture properties that has the ExposedBlob type:
Copy code
@Serializable
data class ProfileSerializer(
    val name: String,
    val bio: String,
    val location: String,
    val website: String,
    val displayPicture: ExposedBlob,
    val bannerPicture: ExposedBlob,
    val dateOfBirth: String,
    @Contextual
    val id: EntityID<Int>,
)
My IDE keeps highlighting that and returns the error message: "Serializer has not been found for type 'ExposedBlob'. To use context serializer as fallback, explicitly annotate type or property with @Contextual"
Also, notice I used the @Contextual annotation for the id property, but that's the only custom serializer that seems to be working. I've created custom serializer for the ExposedBlob data type but it just won't work. Here's my code:
Copy code
object ExposedBlobSerializer : KSerializer<ExposedBlob> {
    override fun serialize(encoder: Encoder, value: ExposedBlob) {
        encoder.encodeBytes(value.bytes)
    }

    override val descriptor: SerialDescriptor
        get() = TODO("Not yet implemented")

    override fun deserialize(decoder: Decoder): ExposedBlob {
        val bytes = decoder.decodeBytes()
        return ExposedBlob(bytes)
    }
}
It keeps raising "Unresolved reference" for the encodeBytes() and decodeBytes() methods.
a
Where did you find those methods?
m
ChatGPT, lol
I don't think they exist though. But I'm wondering if there's some work around for what I'm trying to implement
I need the kotlin serialization library to be able to serialize/deserialize datetime objects, and some other complex stuff.
a
Then either you have to write serializers for classes that miss them or transform objects to serializable classes.
m
How do I do either?
The second one is just a transformation (mapping) from one object to another.
m
For the second one , you mean instead of trying to serialize a datetime object, I can use a string type in place of it?
a
Yeah, something like that
m
Ok, I think I'm already doing something similar. I'll just look up the custom serializer documentation
Thanks
140 Views