Litote / kmongo

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

Filtering for enum with custom value fails with Jackson serialization #371

Closed Xfel closed 2 years ago

Xfel commented 2 years ago
coll.find(Stop::type eq  StopType.STATION).toList()

where StopType is annotated to use int values:

enum class StopType(@JsonValue val value: Int) {
    STATION(1),
    // ...
}

gives exception:

Exception in thread "main" org.bson.BsonInvalidOperationException: readString can only be called when CurrentBSONType is STRING, not when CurrentBSONType is INT32.
    at org.bson.AbstractBsonReader.verifyBSONType(AbstractBsonReader.java:689)
    at org.bson.AbstractBsonReader.checkPreconditions(AbstractBsonReader.java:721)
    at org.bson.AbstractBsonReader.readString(AbstractBsonReader.java:456)
    at org.litote.kmongo.jackson.JacksonCodec.encode(JacksonCodec.kt:199)
    at com.mongodb.client.model.BuildersHelper.encodeValue(BuildersHelper.java:37)
    at com.mongodb.client.model.Filters$SimpleEncodingFilter.toBsonDocument(Filters.java:1190)
    at com.mongodb.internal.operation.Operations.createFindOperation(Operations.java:175)
    at com.mongodb.internal.operation.Operations.find(Operations.java:163)
    at com.mongodb.internal.operation.SyncOperations.find(SyncOperations.java:99)
    at com.mongodb.client.internal.FindIterableImpl.asReadOperation(FindIterableImpl.java:249)
    at com.mongodb.client.internal.FindIterableImpl.asReadOperation(FindIterableImpl.java:41)
    at com.mongodb.client.internal.MongoIterableImpl.execute(MongoIterableImpl.java:135)
    at com.mongodb.client.internal.MongoIterableImpl.iterator(MongoIterableImpl.java:92)
    at kotlin.collections.KMongoIterableKt.kCursor(KMongoIterable.kt:43)
    at kotlin.collections.KMongoIterableKt.useCursor(KMongoIterable.kt:49)
    at kotlin.collections.KMongoIterableKt.toList(KMongoIterable.kt:559)
    at QueryTestKt.main(QueryTest.kt:14)
zigzago commented 2 years ago

As a workaround I suggest you use a custom serializer

HTH

Xfel commented 2 years ago

That does not help.

Using a serializer:

class StopTypeSerializer : JsonSerializer<StopType>() {
    override fun serialize(value: StopType, gen: JsonGenerator, serializers: SerializerProvider?) {
        gen.writeNumber(value.value)
    }
}

I get:

Exception in thread "main" java.lang.IllegalArgumentException: state should be: length >= 5
    at org.bson.assertions.Assertions.isTrueArgument(Assertions.java:62)
    at org.bson.RawBsonDocument.<init>(RawBsonDocument.java:110)
    at org.bson.RawBsonDocument.<init>(RawBsonDocument.java:92)
    at org.litote.kmongo.jackson.JacksonCodec.encode(JacksonCodec.kt:188)

When adding a specific format visitor to the serializer:

    override fun acceptJsonFormatVisitor(visitor: JsonFormatVisitorWrapper, type: JavaType?) {
        visitor.expectIntegerFormat(type)
    }

I instead get:

Exception in thread "main" org.bson.BsonInvalidOperationException: readInt64 can only be called when CurrentBSONType is INT64, not when CurrentBSONType is INT32.
    at org.bson.AbstractBsonReader.verifyBSONType(AbstractBsonReader.java:689)
    at org.bson.AbstractBsonReader.checkPreconditions(AbstractBsonReader.java:721)
    at org.bson.AbstractBsonReader.readInt64(AbstractBsonReader.java:372)
    at org.litote.kmongo.jackson.JacksonCodec.encode(JacksonCodec.kt:195)

Even if I add a toLong() in the serializer, the error stays the same.

zigzago commented 2 years ago

Second workaround (without serializer) - tested ;)

col.find(Stop::type from StopType.STATION.value).toList()

Type checking is bypassed

zigzago commented 2 years ago

fixed in next release