Java fasterxml jackson json date

How to parse JSON with date field in Java — Jackson @JsonDeserialize Annotation Example

I have read many articles on parsing JSON in Java and most of them give examples where properties are either String or int , there are very few examples, where you will see the JSON string contains a date field and that’s one important thing to learn. It’s easy to parse JSON in Java using Jackson or Gson with just integer and string field but you need to do a little more work if your JSON contains a date field because everything in JSON is String but Java is a type-based programming language, where Date is a type.

You have proper classes e.g. java.util.Date or java.time.LocalDate to represent a Date in Java. When you use String to represent a Date, you have to format it into a specific format e.g. dd-MM-yyyy or yyyy-MM-dd and that’s why when you parse or serialize a JSON with a date field, you need to use a custom deserializer to correctly parse the data contained in JSON string properties.

Jackson allows you to do that using @JsonDeserialize annotation. You can annotate a field with this annotation along with the class which Jackson should use to deserialized this field. This is a nice way to provide a class that can correctly format String to date.

For example, you have the following JSON which represents the Effective Java 3rd Edtion book. We have a date field, publicationDate as 27th December, «2017-12-27.

< "title" : "Effective Java", "author" : "Joshua Bloch", "price" : 37, "publicationDate" : "2017-12-27" >

How do we parse this JSON to create an equivalent Book or EBook object in Java? let’s learn that see in this tutorial.

Читайте также:  Execute jar file with java

How to deserialize Date from JSON using Jackson

In order to correct deserialize a Date field, you need to do two things:

1) Create a custom deserializer by extending StdDeserializer class and override its deserialize(JsonParser jsonparser, DeserializationContext context) method. This method should return a Date if we are using this to parse a date field in JSON.

If your date String is in «yyyy-dd-MM» , here is how your implementation of StdDeserializer should look like:

How to parse JSON with date field in Java - Jackson @JsonDeserialize Annotation Example

You can get the value of the date field as String by calling the getText() method of JsonParser class and then you can simply convert it into a Date object by using the parse() method of SimpleDateFormat , as you normally parse Date in Java.

If you are using Java 8 then you can even use the java.time.LocalDate to represent a date and DateTimeFormatter to format/parse dates instead of using SimpleDateFormat class.

If you are not familiar with Java 8 then see The Complete Java Masterclass course on Udemy to learn more about new Date and Time API in Java 8.

2) Next step is to annotate the actual date field in your POJO class using the @JsonDeserialize class as @JsonDeserialize(using = DateHandler.class) as shown below:

class EBook < private String title; private String author; private int price; @JsonDeserialize(using = DateHandler.class) private Date publicationDate; //.. details omitted >

Now, when you parse the JSON String with a date field using ObjectMapper. readValue() method then it will use this DateHandler class to deserialize the date field i.e. publicationDate in our case. Let’s see a live example now:

How to deserialize JSON with the Date field in Java? Example

Here is our complete Java program to parse a JSON with a date attribute in Java using Jackson API. As I said, we have created a custom DateHandler class to convert the string date field into an actual Date object while parsing.

We had just created a DateHandler class and annotated the publicationDate property on EBook object with @JsonDeserialize annotation.

This is enough for Jackson to correctly handle dates in JSON String.

The JSON is contained in the final variable called «json» and I have used my Eclipse tricks to automatically escape JSON while pasting on the String variable, instead of manually putting those forward slash and double-quotes.

It really helps, especially when you quickly want to parse a JSON for testing or debugging purposes. Btw, if you are new to Eclipse IDE, then I suggest you check the Beginners Eclipse Java IDE Training Course, a great course to start with Eclipse.

mport java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.deser.std.StdDeserializer; /* * Java Program to parse JSON with date attribute using Jackson */ public class JacksonTest < private static String json = " + "\"title\" : \"Effective Java\",\r\n" + "\"author\" : \"Joshua Bloch\",\r\n" + "\"price\" : 37,\r\n" + "\"publicationDate\" : \"2017-12-27\"\r\n" + ">"; public static void main(String args[]) throws IOException < // let's parse JSON with a date field ObjectMapper mapper = new ObjectMapper(); EBook effectiveJava = mapper.readValue(json, EBook.class); System.out.println("Input json string"); System.out.println(json); System.out.println("Generated java class: "); System.out.println(effectiveJava); > > /** * POJO or DTO class * @author WINDOWS 8 * */ class EBook < private String title; private String author; private int price; @JsonDeserialize(using = DateHandler.class) private Date publicationDate; public EBook() < >public EBook(String title, String author, int price, Date publicationDate) < super(); this.title = title; this.author = author; this.price = price; this.publicationDate = publicationDate; > public String getTitle() < return title; > public String getAuthor() < return author; > public int getPrice() < return price; > public Date getPublicationDate() < return publicationDate; > public void setTitle(String title) < this.title = title; > public void setAuthor(String author) < this.author = author; > public void setPrice(int price) < this.price = price; > public void setPublicationDate(Date publicationDate) < this.publicationDate = publicationDate; > @Override public String toString() < return "EBook [title color: #006699; font-weight: 700;">+ title + ", author color: #006699; font-weight: 700;">+ author + ", price color: #006699; font-weight: 700;">+ price + ", publicationDate color: #006699; font-weight: 700;">+ publicationDate + "]"; > > /** * Custom Date DeSerializer for JSON * @author WINDOWS 8 * */ class DateHandler extends StdDeserializerDate> < public DateHandler() < this(null); > public DateHandler(Class?> clazz) < super(clazz); > @Override public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException < String date = jsonparser.getText(); try < SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); return sdf.parse(date); > catch (Exception e) < return null; > > > Output: input json string < "title" : "Effective Java", "author" : "Joshua Bloch", "price" : 37, "publicationDate" : "2017-12-27" > generated java class: EBook [title=Effective Java, author=Joshua Bloch, price=37, publicationDate=Wed Dec 27 00:00:00 PST 2017]

You can see that the Date field in the Java class i.e. publicationDate is correctly populated from the JSON String publicationDate attribute, «publicationDate» : «2017-12-27» .

That’s all about how to deal with a JSON string with the date field in Java. As you see, we can easily parse that using Jackson API. It’s really rich and powerful. It provides annotations to hook a custom deserializer for any field and that works like a charm in case of parsing a JSON with a date field in it.

Though, you should remember that this solution will only work in the case of deserializing data because we only wrote a custom deserializer. If you have to generate JSON using a Java object with a Date field then we also need to write a custom serializer. I’ll explain that in the next article, but if you can’t wait, just check JSON with Java APIs on Udemy to learn Jackson API in depth.

Thanks for reading this article so far. If you like this Java JSON tutorial using Jackson API then please share it with your friends and colleagues. If you have any questions or feedback then please drop a note.

Источник

Jackson – Serialize and Deserialize Dates

By default, Jackson serializes the Dates in numeric format. Learn to customize the serialization and deserialization of date and time types in Java using Jackson.

Add the latest version of Jackson, if you have already added it to the project.

 com.fasterxml.jackson.dataformat jackson-dataformat-xml 2.13.3 

For demo purposes, we will use the following Message class.

@JsonInclude(JsonInclude.Include.NON_NULL) class Message < private Long id; private String text; private Date date; private LocalDateTime localDateTime; //constructors, getters, setters >

2. Default Serialization and Deserialization

The default serialization and deserialization of java.util.Date and other date-time types such as java.time.LocalDateTime is done in numeric formats. The Date is converted to the long type and other types are converted to string with number values.

To include support for new Java 8 Date Time classes, do not forget to include the JavaTimeModule to the JsonMapper or ObjectMapper.

Let us see the serialization with an example.

@Test void testDefaultSerialization_ThenSuccess() throws JsonProcessingException < Message message = new Message(1L, "test"); message.setDate(new Date(1661518473905L)); message.setLocalDateTime(LocalDateTime.of(2022,8,30,14,16,20,0)); JsonMapper jsonMapper = new JsonMapper(); jsonMapper.registerModule(new JavaTimeModule()); String json = jsonMapper.writeValueAsString(message); Assertions.assertEquals("", json); >

Also, check out the deserialization from JSON to POJO as follows:

@Test void testDefaultDeserialization_ThenSuccess() throws JsonProcessingException < String json = ""; JsonMapper jsonMapper = new JsonMapper(); jsonMapper.registerModule(new JavaTimeModule()); Message message = jsonMapper.readValue(json, Message.class); Assertions.assertEquals(1661518473905L, message.getDate().getTime()); Assertions.assertEquals(LocalDateTime.of(2022,8,30,14,16,20,0), message.getLocalDateTime()); >

3. Using Custom Date Time Patterns

For serializing the date time types using custom patterns, we can set the SimpleDateFormat to JsonMapper.

jsonMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));

Now we can use this JsonMapper instance to write supported types using the configured custom pattern.

@Test void testCustomFormat_ThenSuccess() throws JsonProcessingException < Message message = new Message(1L, "test"); message.setDate(new Date(1661518473905L)); message.setLocalDateTime(LocalDateTime.of(2022, 1, 1, 15, 30)); JsonMapper jsonMapper = new JsonMapper(); jsonMapper.registerModule(new JavaTimeModule()); jsonMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); String json = jsonMapper.writeValueAsString(message); Assertions.assertEquals("", json); >

Note that not all Java types support all custom patterns. For example, in the above code, if we use the LocalDate class, it will not give the desired result because there is no time information associated with the LocalDate class.

The deserialization process is very similar to serialization. It also uses the custom pattern configured using the SimpleDateFormat class.

@Test void testCustomDateFormatDeserialization_ThenSuccess() throws JsonProcessingException < String json = ""; JsonMapper jsonMapper = new JsonMapper(); jsonMapper.registerModule(new JavaTimeModule()); jsonMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")); Message message = jsonMapper.readValue(json, Message.class); Assertions.assertEquals(1661518473905L, message.getDate().getTime()); Assertions.assertEquals("2022-08-30T14:16:20", message.getLocalDateTime().toString()); >

4. Custom Serializer and Deserializer

If we want more control over how the JSON to POJO (or vice-versa) conversions happen, we can write custom classes and register them with Jackson.

The following is an example of a simple custom date serializer for LocalDateTime type. It extends StdSerializer class and override its serialize() method.

We can apply any custom pattern using the Java DateTimeFormatter class. We can customize it based on our complex requirements.

class CustomLocalDateTimeSerializer extends StdSerializer  < private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"); public CustomLocalDateTimeSerializer() < this(null); >public CustomLocalDateTimeSerializer(Class t) < super(t); >@Override public void serialize( LocalDateTime value, JsonGenerator gen, SerializerProvider arg2) throws IOException, JsonProcessingException < gen.writeString(formatter.format(value)); >>

Note that we are not using Jackson’s support to process LocalDateTime class, so we can skip adding the JavaTimeModule module. Instead, we can add a SimpleModule after registering CustomLocalDateTimeSerializer with it.

@Test void testCustomSerializer_ThenSuccess() throws JsonProcessingException < Message message = new Message(1L, "test"); message.setLocalDateTime(LocalDateTime.of(2022, 1, 1, 15, 30)); JsonMapper jsonMapper = new JsonMapper(); SimpleModule module = new SimpleModule(); module.addSerializer(LocalDateTime.class, new CustomLocalDateTimeSerializer()); jsonMapper.registerModule(module); String json = jsonMapper.writeValueAsString(message); Assertions.assertEquals("", json); >

Adding a custom date deserializer is similar to what we saw in the custom serializer. It extends StdDeserializer class.

class CustomLocalDateTimeDeserializer extends StdDeserializer  < private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); public CustomLocalDateTimeDeserializer() < this(null); >public CustomLocalDateTimeDeserializer(Class vc) < super(vc); >@Override public LocalDateTime deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException < String date = jsonparser.getText(); return LocalDateTime.parse(date, formatter); >>

Let us test the custom deserialization using a simple example.

@Test void testCustomLocalDateTimeDeserializer_ThenSuccess() throws JsonProcessingException < String json = ""; JsonMapper jsonMapper = new JsonMapper(); SimpleModule module = new SimpleModule(); module.addDeserializer(LocalDateTime.class, new CustomLocalDateTimeDeserializer()); jsonMapper.registerModule(module); Message message = jsonMapper.readValue(json, Message.class); Assertions.assertEquals("1986-04-08T12:30", message.getLocalDateTime().toString()); >

In this Jackson tutorial, we learned the default serialization and deserialization of Java Date and Time type classes. We also learned to use the custom patterns using the SimpleDateFormat, and custom serializer and deserializer implementations.

Источник

Оцените статью