Litote / kmongo

[deprecated] KMongo - a Kotlin toolkit for Mongo
https://litote.org/kmongo/
Apache License 2.0
781 stars 73 forks source link

projections does not work for root class with typed parameters like Collection or Map #281

Open jakobkmar opened 3 years ago

jakobkmar commented 3 years ago

Let's assume that I have a class called Identifier, and a serializer for that class called IdentifierSerializer, which serializes the Identifier to a String.

Now inside of the class representing the documents of a collection, there is a field of the type Identifier, e.g.:

class MyDocumentClass(
    val identifiers: List<@Serializable(with = IdentifierSerializer::class) Identifier>,
    //... more fields, therefore the projection function makes sense
)

Now I want to use projection in the following way:

val currentIdentifiers: List<Identifier> = db.myCollection.projection(
    MyDocumentClass::identifiers,
    theQuery
)

Now to the bug:

Somewhere inside of the projection call, there has to be an unsafe cast. Because currentIdentifiers is actually a List<String> which it should not be - its type even is List<Identifier>.

Obviously, the custom serializer has not been used for deserialization of the returned array members in the database, instead projection did just return the actual raw content of the array in the database (which is the output of the serialize function of the custom serializer, which has been used correctly earlier on) and casted it to the desired type in an unsafe way.

An example for what would fail now:

currentIdentifiers.map { it.namespace }

This of course fails, because String does not have a property called namespace.

This should be fixed, because typesafety has been lost in this case.

zigzago commented 3 years ago

Thank you for reporting. The problem is that projection does not support (for now) type parameters for their root class.

As a workaround, I suggest to use a custom dedicated class for projection as specified in the doc https://litote.org/kmongo/extensions-overview/#projection . Look at the attached unit test.