Jackson How-To: Custom Deserializers
Writing custom deserializes is easy: you just need to extend JsonDeserializer abstract class. It operates on Streaming API: reads JSON tokens, and produces a single Java object (of declared type).
Instead of directly starting with JsonDeserializer, it is common to sub-class org.codehaus.jackson.map.deser.StdDeserializer, which has commonly needed functionality that can simplify writing of custom deserializers.
Here are other things you need to be aware of.
Registering custom deserializers
With Jackson 1.7 and above
1 ObjectMapper mapper = new ObjectMapper(); 2 SimpleModule testModule = new SimpleModule("MyModule", new Version(1, 0, 0, null)) 3 .addDeserializer(MyType.class, new MyTypeDeserializer()); 4 mapper.registerModule(testModule);
For more advanced handling of deserializers to types they handle, you may need to implement Module interface directly; this will give more control over exact matching logic. This may be necessary when dealing with generic types.
With Jackson 1.0 - 1.6
To be able to use custom deserializers, you first need to either create your own DeserializerFactory that can serve these serializers, or create an instance of CustomDeserializerFactory (and register deserializers with it). And then you need to configure ObjectMapper to use the factory. Here is one way to do this:
ObjectMapper mapper = new ObjectMapper(); CustomDeserializerFactory sf = new CustomDeserializerFactory(); // provider owns factory, mapper uses provider (standard provider works for us) mapper.setDeserializerProvider(new StdDeserializerProvider(sf)); // deserializers are mapped by declared type; always specific (no generic binding like with serialization) sf.addSpecificMapping(MyBean.class, new MyBeanDeserializer());
which would allow serialization of properties that have declared type of MyBean (or, when using polymorphic type information, properties that had actual type of MyBean, as indicated by embedded type information)
Writing custom deserializers
Basic rules for deserializers is that deserializer:
- May get a JSON value of any type given to it, and has to verify that type it gets is acceptable (and if not, signal error by throwing exception) -- some deserializers accept multiple types o JSON input, others only one specific type
Is passed JsonParser that is positioned over first token it is to handle, which is:
- the (only) token it is to handle, for scalar types
- opening START_ARRAY for JSON Array
- either START_ELEMENT or FIELD_NAME for JSON Object -- latter may occur when embedded type information for polymorphic type handling has been processed.
- needs to process all tokens related to the value; this includes closing END_ARRAY for JSON Arrays and END_OBJECT for JSON objects.
- must NOT process any token beyond value being deserialized (no more, or no less)
Need NOT worry about polymorphic type information: this is handled by type deserializers, which call actual deserializers.