Json Date Serialization Jackson
What is the formatting I need to use to carry out conversion with Jackson? Is Date a good field type for this? Date is a fine field type for this. You can make the JSON parse-able pretty easily by using ObjectMapper.setDateFormat: DateFormat df = new SimpleDateFormat('yyyy-MM-dd HH:mm a z'); myObjectMapper.setDateFormat(df). You make a nice restfull api using annotation driven controllers, and jackson mapping until you discover that the date serialization gives you a timestamp. This one Gives you this one:( You can just get away with by changing the mapper configuration. And the world is a better place This is a quick one,.
[Questo articolo è disponibile anche in ITALIANO: Serializzazione e deserializzazione JSON di oggetti Java con Jackson: un esempio concreto]
In this post we see how to use the Jackson framework to serialize simple Java objects (POJOs – plain Old Java Object) in JSON (JavaScript Object Notation), the textual format quick and easy to process for data exchange between applications, and also how to perform the inverse transformation, from a text string in JSON format containing the object information to the Java object itself(deserialization).
To do this we create some simple class with which we represent an e-commerce orders management system. So we will have orders, customers, the list of the items included in the order, with their quantity, price, etc ..
So, let’s start to define the classes we need. We start from the Order class that will contain the order identifier, the customer who placed the order, the list of the lines that compose the order, the total amount of the order and the date on which the order was placed.
We have redefined the toString method to obtain an explanatory text representation of our Order objects.
At this point we define the OrderItem class representing individual lines of an order which will be constituted by the purchased item, the relative number of pieces and the total price for this row, given by the multiplication between the quantity and price of each item.
We continue in the definition of classes with Item, which simply represents an item available for purchase. His fields are an identifier, the name of the object itself, its category of membership and its unit price. The category is represented by an enumerator that we will define shortly after.
Now, we define the enumerator of the categories:
Finally, we define the Customer class, which represents clients that we identify simply by an id and their name and surname.
Now that we have defined the necessary classes, we create a small test program that creates an Order object and prints it on the screen:
Trying to run the program we get the following output:
Ok, now let’s go back to our goal, which is to provide an example of JSON serialization with Jackson.
First, add the Jackson libraries to the Build Path of our project; the jar to be included, as shown in the following figure, are those of the three modules in which the Jackson project has been divided:
– Core
– DataBind
– Annotations
Once we have added the libraries to the project, we modify our test program to perform the JSON serialization of our Order object.
What we need to do is to create an ObjectMapper and invoke its writeValue method, passing as parameters the stream where to write the value (in our case System.out, the standard output) and the object to be serialized (our Order object).
Here’s the updated code of our test program:
Here we see the (very long) string resulting from the serialization process:
Displayed in this way, the string isn’t simple to analyze and for this reason we ask the object of ObjectMapper to format the output in a more readable way, just for verification purposes.
To do that we set the mapper as follows:
or, alternatively:
Running again our test program we get this time the string formatted as follows:
As we can see our Order object is represented by an associative array of key-value pairs, enclosed in braces. The first field, “id” is a primitive type so that its value is just reported. The field “customer” instead, consists in an object of the Customer class, so in the serialization process as a new object is defined, opening a new brace, inside of which are represented the Customer object attributes. The next field of the Order class to represent in the JSON string is “itemList” which at the class level is defined as a list of OrderItem. The lists are represented in JSON within square brackets, so in our serialization string we have the field “itemList” displayed by a pair of square brackets within which are listed, separated by commas, the representations of OrderItem objects. Each OrderItem element, being an object of a class, is enclosed in curly braces and contains the fields “quantity”, “it” enclosed in braces because, again, is an Item object, and “price”. Finally the Order object provides the last two simple fields, “total” and “placedDate”. On this last field, representing the date on which the order was placed, we notice something strange. The date is represented in the “computer age” format, so as the number of milliseconds since 01-01-1970. To give it a more readable we have to act again on our ObjectMapper object, setting the desired format.
Running again our test program for the serialization of our Order object we get the following result:
As we can see from the generated output, the date this time is represented by the specified format and is therefore readable:
Let’s look now at the de-serialization process. First we make a change to our testing program in order to let it write the string containing the JSON serialization of our Order on a String object instead of printing it on video. For this purpose we replace the invocation of the methodwriteValue on our ObjectMapper with the invocation of the method writeValueAsString that gives us the JSON as a String:
The result is the same as before, when we wrote the JSON directly to standard output by the method writeValue.
At this point we have our JSON saved in a String, so we can try to make deserialization using the readValue. We modify our test program telling it to create an Order java oject starting from its JSON representation saved in the string.
Executing the program we get this result:
This means that we must indicate which constructor we want to use to instantiate an object of Order class, starting from its JSON representation. To do this we must annotate the constructor to be used with the Jackson annotation “@JsonCreator” and annotate every constructor parameter with the Jackson annotation “@JsonProperty” combined with class property that parameter maps.
Now we modify the Order class constructor as follows:
Trying to re-run the test program we get:
As we can see, this time the error was “moved” to the constructor of the Customer class, so the configuration that we have provided for the Order class constructor was correct. We repeat the same configuration through Jackson annotations for the constructors of all our classes. They then become as follows:
Json Date Serialization Jackson Hole
Once configured all constructors to be used use during deserialization process, we run again our test program and we get the following result:
The result, as you can see, shows:
– The toString of the Order java class object
– The JSON representation of the object obtained from serialization process
– The toString of the new Order java object created through deserialization of JSON string
The complete code example is available for download here: