Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to use JsonIdentityInfo with this lib? #135

Closed
bognari opened this issue May 13, 2019 · 2 comments
Closed

How to use JsonIdentityInfo with this lib? #135

bognari opened this issue May 13, 2019 · 2 comments

Comments

@bognari
Copy link

bognari commented May 13, 2019

Hi I have an Object like this:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator::class , property= "uri")
class Entry(val uri: String) {
    @JsonIdentityReference(alwaysAsId = true)
    var contains : MutableSet<Entry> = Collections.synchronizedSet(HashSet())
}

When I use the JacksonMapper from the KMongoConfiguration I get an valid JSON in with "contains" contains only the URIs from the containing entries.
But when I try to Insert it into the MongoDB I get this Exception:

Caused by: java.lang.IllegalStateException: XXX has to be class org.bson.types.ObjectId
	at org.litote.kmongo.jackson.KMongoBsonFactory$KMongoBsonGenerator.writeObjectId(KMongoBsonFactory.kt:49)
	at com.fasterxml.jackson.databind.ser.impl.WritableObjectId.writeAsField(WritableObjectId.java:67)
	at com.fasterxml.jackson.databind.ser.std.BeanSerializerBase._serializeWithObjectId(BeanSerializerBase.java:627)
	at com.fasterxml.jackson.databind.ser.BeanSerializer.serialize(BeanSerializer.java:148)
	at com.fasterxml.jackson.databind.ser.DefaultSerializerProvider._serialize(DefaultSerializerProvider.java:480)

If I change the Object to this I get the exception also...

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator::class , property= "_id")
class Entry(uri: String) {
    @BsonId 
    val _id: Id<Entry> = StringId(uri)
    @JsonIdentityReference(alwaysAsId = true)
    var contains : MutableSet<Entry> = Collections.synchronizedSet(HashSet())

As far as I can see the StringID Object are changed to a String inside Jackson

public void writeAsField(JsonGenerator gen, SerializerProvider provider,
            ObjectIdWriter w) throws IOException
    {
        idWritten = true;

        // 03-Aug-2013, tatu: Prefer Native Object Ids if available
        if (gen.canWriteObjectId()) {
            // Need to assume String(ified) ids, for now... could add 'long' variant?
            gen.writeObjectId(String.valueOf(id));
            return;
        }
        
        SerializableString name = w.propertyName;
        if (name != null) {
            gen.writeFieldName(name);
            w.serializer.serialize(id, gen, provider);
        }
    }
@zigzago
Copy link
Member

zigzago commented May 14, 2019

Well... KMongo did not support to generate id as String with @JsonIdentityInfo. This is fixed in snapshot.
Here is a way to generate an Id with the fix:

@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator::class, property = "uri")
class Entry() {

        constructor(uri:String) : this() {
            this.uri = uri
        }

        lateinit var uri: String

        @JsonIdentityReference(alwaysAsId = true)
        var contains: MutableSet<Entry> = Collections.synchronizedSet(HashSet())

    }

There is a bug in jackson-module-kotlin lib, so you can't place the id in primary constructor.

With this solution, the bson in mongo looks like this:

{"_id": "http://litote.org/kmongo", "uri": "http://litote.org/kmongo", "contains": []}

HTH

@bognari
Copy link
Author

bognari commented May 14, 2019

Thanks for the fast response and sorry for my bad mood yesterday.
I tested the fix today and it works as described. Thank you very much.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants