Skip to content

Instantly share code, notes, and snippets.

@JaiHirsch
Created March 29, 2015 16:51
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save JaiHirsch/08397223c2a0de64dfc8 to your computer and use it in GitHub Desktop.
Save JaiHirsch/08397223c2a0de64dfc8 to your computer and use it in GitHub Desktop.
MongoDB 3.0 java driver Codec example - Codec class for the mapping the Grades bean
package org.scratch;
import org.bson.BsonReader;
import org.bson.BsonString;
import org.bson.BsonValue;
import org.bson.BsonWriter;
import org.bson.Document;
import org.bson.codecs.Codec;
import org.bson.codecs.CollectibleCodec;
import org.bson.codecs.DecoderContext;
import org.bson.codecs.DocumentCodec;
import org.bson.codecs.EncoderContext;
import org.bson.types.ObjectId;
public class GradesCodec implements CollectibleCodec<Grades> {
private Codec<Document> documentCodec;
public GradesCodec() {
this.documentCodec = new DocumentCodec();
}
public GradesCodec(Codec<Document> codec) {
this.documentCodec = codec;
}
@Override
public void encode(BsonWriter writer, Grades value,
EncoderContext encoderContext) {
Document document = new Document();
ObjectId id = value.getId();
Double score = value.getScore();
Integer studentId = value.getStudentId();
String type = value.getType();
if (null != id) {
document.put("_id", id);
}
if (null != score) {
document.put("score", score);
}
if (null != studentId) {
document.put("student_id", studentId);
}
if (null != type) {
document.put("type", type);
}
documentCodec.encode(writer, document, encoderContext);
}
@Override
public Class<Grades> getEncoderClass() {
return Grades.class;
}
@Override
public Grades decode(BsonReader reader, DecoderContext decoderContext) {
Document document = documentCodec.decode(reader, decoderContext);
System.out.println("document "+document);
Grades grade = new Grades();
grade.setId(document.getObjectId("_id"));
grade.setStudentId(document.getInteger("student_id"));
grade.setType(document.getString("type"));
grade.setScore(document.getDouble("score"));
return grade;
}
@Override
public Grades generateIdIfAbsentFromDocument(Grades document) {
return documentHasId(document) ? document.withNewObjectId() : document;
}
@Override
public boolean documentHasId(Grades document) {
return null == document.getId();
}
@Override
public BsonValue getDocumentId(Grades document) {
if (!documentHasId(document))
{
throw new IllegalStateException("The document does not contain an _id");
}
return new BsonString(document.getId().toHexString());
}
}
@pgifford
Copy link

Shouldn't documentHasId return false if document.getId() is null?

@growlingchaos
Copy link

Very helpful, thank you!

@WardLootens
Copy link

Shouldn't generateIdIfAbsentFromDocument return the document itself when it has an id, and document.withNewObjectId when it hasn't?

@estet90
Copy link

estet90 commented Sep 10, 2017

заебись!

@solox174
Copy link

solox174 commented Mar 22, 2018

This example got me on track, thank you. There are a few other ways I've see people try to do this that were a lot less clean. Some possible improvements to your example would be fixing the inverted generateIdIfAbsentFromDocument logic. It also doesn't throw an error if there is no Id. I read through the DocumentCodec class source and it was edifying. Also, if you add BsonTypeClassMap to your GradesCodecProvider constructor and pass that through to the GradesCodec constructor where they can be passed to the constructor of your DocumentCodec instance, per http://mongodb.github.io/mongo-java-driver/3.4/bson/codecs/#codecprovider, your Grades class (or other peoples classes), can have complex field types without a bunch of complex conversion logic in the GradesCodec. I implemented this and it ended up being very clean. I would share the code but it's not open source (company code). Thanks again.

@SyCode7
Copy link

SyCode7 commented Sep 18, 2018

Hi, this really helped me, thank you very much. However, I am struggling how to serialize/deserialize a Date field.
I have tried using the something like this in the Codec implementation:
Date timestamp = value.getTimestamp();

However, I still have null results.

@neeraj2681
Copy link

Thanks man!

@ron-mcleod
Copy link

Thanks! Your example code helped me migrate my Codec from streaming based to document based.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment