Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Custom deserialization on top of reflective deserialization with Jackson

Tags:

java

json

jackson

I want to run some custom code when deserializing a particular type with Jackson 1.9. However, I don't want to hand-write the whole deserializer, just add to the default behaviour. Trying to do this in a JsonDeserializer the naive way results in infinite recursion, however. Currently, my approach uses a completely separate ObjectMapper, but that feels like a huge hack.

private static class SpecialDeserializer extends JsonDeserializer<Special> {
    @Override
    public Special deserialize(JsonParser jp, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
        JsonNode jsonNode = jp.readValueAsTree();
        ObjectMapper otherMapper = getOtherMapper();
        Special special = otherMapper.readValue(jsonNode, Special.class);
        special.setJsonNode(jsonNode);
        return special;
    }
}
like image 946
Tavian Barnes Avatar asked Jan 31 '14 00:01

Tavian Barnes


2 Answers

Polymorphic deserialization should be able to handle deriving the type of the input from the content of the input. If that's what you need the custom deserialization for, you can achieve it via annotations. See this example for reference.

(Apologies for not answering the actual question; this answers what I'm inferring to the "root" question, from the poster's comment).

like image 196
Paul Hicks Avatar answered Sep 21 '22 03:09

Paul Hicks


If you want to implement this special behavior only for one class, you can create additional type with the same properties set. I am not sure that this is a real answer for your question, but see my below example. POJO class with property:

@JsonDeserialize(using = SpecialJsonDeserializer.class)
class Special {

    private String name;

    //getters, setters, toString
}

Deserializer with inner type:

class SpecialJsonDeserializer extends JsonDeserializer<Special> {
    @Override
    public Special deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException,
            JsonProcessingException {
        InnerSpecial innerSpecial = jp.readValueAs(InnerSpecial.class);

        return innerSpecial.createRealSpecial();
    }

    private static class InnerSpecial {

        public String name;

        public Special createRealSpecial() {
            Special special = new Special();
            // copy other properties, add additional code
            special.setName(name);

            return special;
        }
    }
}

And simple usage:

public class JsonProgram {

    public static void main(String[] args) throws IOException {
        Special special = new Special();
        special.setName("ye");

        ObjectMapper mapper = new ObjectMapper();
        String json = mapper.writeValueAsString(special);
        System.out.println(json);
        System.out.println(mapper.readValue(json, Special.class));
    }
}

I think, this is a little bit less hack than yours but it is still hack.

like image 35
Michał Ziober Avatar answered Sep 18 '22 03:09

Michał Ziober