Handling MongoDB ObjectId threw Jersey/Jackson

If you are using Jersey and MongoDB on same project, you already know what I’m talking about: ObjectId is a mess for Jackson, it is not able to handle it properly…

So today, a basic trick how to parse this type of field, in a proper way.

Basic idea

Jackon allow many way of handling difficult types, only one way is « really clean », they does consider to let you interfer the way Jackson works for serializing. We will use that way to create our custom JsonSerializer. Of course, you can extend this tutorial to other data type…

Basically we will define a parser for ObjectId itself, and another one if you want to use a List (java.util one) of ObjectId (for example purpose)…

ObjectId handling

Lets define a bean :

import org.bson.types.ObjectId;
import java.util.List;

class myBean {
	private ObjectId id;
	private List<ObjectId> children;

	public ObjectId getId() {return this.id;}
	public void setId(ObjectId id) {this.id = id;}
	public List<ObjectId> getChildren() {return this.children;}
	public void setChildren(List<ObjectId> children) {this.children = children;}
}

Now if you create an object myBean, and render it threw jersey/jackson, you will see the id is converted to a kind of sub-object. Worst, if you try to handle this to serialize from json, it will fail.

The solution here goes from Serializer provider, allowing you to handle specific behaviour on some items, lets define the first one, for ObjectId :

import java.io.IOException;

import org.bson.types.ObjectId;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

/**
 * Custom Json serializer for ObjectId type
 * 
 * @author Deisss (LGPLv3)
 * @version 0.1
 */
public class ObjectIdJsonSerializer extends JsonSerializer<ObjectId> {
	@Override
	public void serialize(ObjectId o, JsonGenerator j, SerializerProvider s) throws IOException, JsonProcessingException {
		if(o == null) {
			j.writeNull();
		} else {
			j.writeString(o.toString());
		}
	}
}

If the ObjectId is null, we send back null, and on other case, we call a toString, unfortunately, Jackson behaviour is not this one. Doing that trick work as expected, now we still have to link it with our bean :

import org.bson.types.ObjectId;
import java.util.List;
import org.codehaus.jackson.map.annotate.JsonSerialize;

class myBean {
	private ObjectId id;
	private List<ObjectId> children;

	@JsonSerialize(using=ObjectIdJsonSerializer.class)
	public ObjectId getId() {return this.id;}
	public void setId(ObjectId id) {this.id = id;}
	public List<ObjectId> getChildren() {return this.children;}
	public void setChildren(List<ObjectId> children) {this.children = children;}
}

And we are done ! Nothing more to do, now it works as expected !

Let’s continue on List item, quite the same…

List handling

Let’s start directly with Serializer, just because it’s quite the same way :

import java.io.IOException;
import java.util.List;

import org.bson.types.ObjectId;
import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.SerializerProvider;

/**
 * Custom Json serializer for List ObjectId type
 * 
 * @author Deisss (LGPLv3)
 * @version 0.1
 */
public class ListObjectIdJsonSerializer extends JsonSerializer<List<ObjectId>> {
	@Override
	public void serialize(List<ObjectId> list, JsonGenerator j, SerializerProvider s) throws IOException, JsonProcessingException {
		if(list == null) {
			j.writeNull();
		} else {
			j.writeStartArray();
			for(ObjectId o : list)
			{
				j.writeString(o.toString());
			}
			j.writeEndArray();
		}
	}
}

Woot Woot ! Now it is finally setup as expected, just do exactly the same trick on the bean, but this time of course on list getter, and we are done !

Final words

Jersey is great, Jackson too, need to say more ? I don’t think so, handling custom behaviour is quite easy, and can be pretty powerfull ! Have fun with it !

Publicités

2 Commentaires

  1. Would be nice to see Deserializer as well…

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :