Jackson is a powerful library which can automatically serialize to and from JSON to Java and I have made extensive use of it in my projects. To integration with jackson you annotate the fields within your POJOs with the @JsonProperty annotation. Then using a JSON Mapper you can convert the POJOs to JSON and JSON to POJOs. For more details see my earlier article (Polymorphic JSON Serialization using Jackson). However, sometimes the default behavior of the jackson mapper falls short. In one of my projects I needed to serialize a Java class to a specific integer field within that object. This is not possible using the default ObjectMapper or its serialization config. This is where custom serializes come in using Json Serializer comes to the rescue. This article describes the use of custom serializers and deseralizers with the Jackson library.
Getting started
As a starting point I will use the code in my earlier article Polymorphic JSON Serialization using Jackson which can be downloaded at gitbub.
In the source files you downloaded open Child1.java, look for the SerializeMe property. It is annotated with the JSON Property and will there for be serialized to an integer. What if we wanted to write the string representation of the integer rather than a number. i.e. If the field value was 3 we would write it as “three”. The first step is to annotate the property with the @JsonSerialize and @JsonDeserialize annotations and provide the custom classes we want to use for serialization and deserialization as shown below.
Implementing the Custom Serializer
In order to implement a custom serializer we must extend the JsonSerializer class and define the template type to be the type for our annotated field. In our case the annotated field is on “int” type. Primitive types are automatically boxed into their respective object types, hence we will be using the Integer type. We override the serialize method which will receive the value of the field in the value parameter. Using the input value we can define what output we want to generate and then write it using the generator parameter. The generator class has many functions for writing the various Json types, we will be using the writeString method for our serializer however a complete list of methods is available here. I am writing a a small converter which generates the string value of input integers, see code below.
Implementing the Custom Deserializer
You can setup custom object deserialization in exactly the same fashion by extending the JsonDeserializer class and overriding the deserialize method. This method has a parser parameter which we can use to retrieve the Json data as shown below.
Testing the code
Open up the Driver.java file from the downloaded sources and replace the main method with the code shown below. In this code we are creating and initializing an instance of the Child1 class and then writing it using a Jackson Object mapper. When you run this code you should see {"objectType":"Child1","SerializeMe":"three"}. If you delete the annotations from the Child one class and rerun the code you should see {"objectType":"Child1","SerializeMe":3}. When we deserialize we see that the value is again stored in the object as 3. This simple and admittedly contrived example shows the power of custom serializers. I have used these in several projects to format responses according to client requirements without impacting server Object designs.
Source code
The source code for this project is released under the BSD License and can be downloaded at github.