Jackson 1.x to 2.x Migration; JsonDeserializer, ObjectMapper and DeserializationContext

708 views
Skip to first unread message

Ryon Day

unread,
Mar 14, 2014, 12:44:14 PM3/14/14
to jackso...@googlegroups.com
Hello,

I'm currently migrating some Jackson 1.x code to Jackson 2.x. I have read the general overview of this kind of thing, but have come across some cases that are not specifically addressed, and my Google searches haven't borne too much fruit either. Let's take some example code and assume that I've already built up that false sense of confidence that this will be simple by search-and-replacing the package names in the source tree. We have this:

public class ThingieDeserializer extends JsonDeserializer<Thingie> {
@Override
public Thingie deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
mapper.setDeserializationConfig(ctxt.getConfig());
jp.setCodec(mapper);
if (jp.hasCurrentToken()) {
JsonNode dataNode = jp.readValueAsTree();
if (dataNode != null) {
return (Thingie) mapper.readValue(dataNode,new TypeReference<Thingie>(){});
}
}
return null;
}
}

So I have so far ended up with this (see bolded areas):

public class ThingieDeserializer extends JsonDeserializer<Thingie> {
@Override
public Thingie deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
ObjectMapper mapper = new ObjectMapper();
// mapper.setDeserializationConfig(ctxt.getConfig()); // Does not compile :(
jp.setCodec(mapper);
if (jp.hasCurrentToken()) {
JsonNode dataNode = jp.readValueAsTree();
if (dataNode != null) {
return mapper.readValue(dataNode.traverse() /* Correct? At least it compiles... */,new TypeReference<Thingie>(){});
}
}
return null;
}
}

I am relatively happy with the .traverse() addition; the real record-scratch, stop-the-party moment comes with the removal of setDeserializationConfig() from ObjectMapper (. There seems to be no immediate substitute or equivalent for this method, and I cannot wrap my head around what negative repercussions removing this line entirely would cause. I noticed that ObjectMapper does have a constructor with a DeserializationContext parameter, but looking at the source code it does not use that DeserializationContext's DeserializationConfig (??!!).

So my question is: What is the Jersey 2.x equivalent to the Jersey 1.x operation above?

Thanks!

Ryon

Tatu Saloranta

unread,
Mar 15, 2014, 1:09:15 AM3/15/14
to jackso...@googlegroups.com
Basically, creation of a new ObjectMapper() from custom deserializer is a wrong thing to do.
It is a huge performance hit, and best avoided.
Instead, you can get access using

ObjectMapper mapper = (ObjectMapper) jp.getCodec();

although I do not quite grasp what on earth custom deserializer is trying to do from there on -- isn't it causing infinite loop? You can't just claim to deserialize X, read JSON as a tree, then delegate back to mapper to deserialize into X.

-+ Tatu +-


Reply all
Reply to author
Forward
0 new messages