diff --git a/jackson/pom.xml b/jackson/pom.xml index 569c7f5028..247bab72b0 100644 --- a/jackson/pom.xml +++ b/jackson/pom.xml @@ -45,6 +45,12 @@ ${jackson.version} + + joda-time + joda-time + 2.6 + + com.google.code.gson gson diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java new file mode 100644 index 0000000000..bbd039f6ae --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateDeserializer.java @@ -0,0 +1,27 @@ +package org.baeldung.jackson.date; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonParser; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.DeserializationContext; +import com.fasterxml.jackson.databind.JsonDeserializer; + +public class CustomDateDeserializer extends JsonDeserializer { + + private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + @Override + public Date deserialize(final JsonParser jsonparser, final DeserializationContext context) throws IOException, JsonProcessingException { + final String date = jsonparser.getText(); + try { + return formatter.parse(date); + } catch (final ParseException e) { + throw new RuntimeException(e); + } + } + +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java new file mode 100644 index 0000000000..fc7cbb2db1 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateSerializer.java @@ -0,0 +1,20 @@ +package org.baeldung.jackson.date; + +import java.io.IOException; +import java.text.SimpleDateFormat; +import java.util.Date; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class CustomDateSerializer extends JsonSerializer { + + private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + @Override + public void serialize(final Date value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.format(value)); + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java new file mode 100644 index 0000000000..9f2a290bc4 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomDateTimeSerializer.java @@ -0,0 +1,22 @@ +package org.baeldung.jackson.date; + +import java.io.IOException; + +import org.joda.time.DateTime; +import org.joda.time.format.DateTimeFormat; +import org.joda.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class CustomDateTimeSerializer extends JsonSerializer { + + private static DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm"); + + @Override + public void serialize(final DateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.print(value)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java new file mode 100644 index 0000000000..b1e6a8ba86 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/CustomLocalDateTimeSerializer.java @@ -0,0 +1,20 @@ +package org.baeldung.jackson.date; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import com.fasterxml.jackson.core.JsonGenerator; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonSerializer; +import com.fasterxml.jackson.databind.SerializerProvider; + +public class CustomLocalDateTimeSerializer extends JsonSerializer { + + private static DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + + @Override + public void serialize(final LocalDateTime value, final JsonGenerator gen, final SerializerProvider arg2) throws IOException, JsonProcessingException { + gen.writeString(formatter.format(value)); + } +} \ No newline at end of file diff --git a/jackson/src/test/java/org/baeldung/jackson/date/Event.java b/jackson/src/test/java/org/baeldung/jackson/date/Event.java new file mode 100644 index 0000000000..783eee6af8 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/Event.java @@ -0,0 +1,25 @@ +package org.baeldung.jackson.date; + +import java.util.Date; + +public class Event { + public String name; + public Date eventDate; + + public Event() { + super(); + } + + public Event(final String name, final Date eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public Date getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java b/jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java new file mode 100644 index 0000000000..4b2053eb4b --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/EventWithFormat.java @@ -0,0 +1,29 @@ +package org.baeldung.jackson.date; + +import java.util.Date; + +import com.fasterxml.jackson.annotation.JsonFormat; + +public class EventWithFormat { + public String name; + + @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "dd-MM-yyyy hh:mm:ss") + public Date eventDate; + + public EventWithFormat() { + super(); + } + + public EventWithFormat(final String name, final Date eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public Date getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java b/jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java new file mode 100644 index 0000000000..0c72030650 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/EventWithJodaTime.java @@ -0,0 +1,29 @@ +package org.baeldung.jackson.date; + +import org.joda.time.DateTime; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class EventWithJodaTime { + public String name; + + @JsonSerialize(using = CustomDateTimeSerializer.class) + public DateTime eventDate; + + public EventWithJodaTime() { + super(); + } + + public EventWithJodaTime(final String name, final DateTime eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public DateTime getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java b/jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java new file mode 100644 index 0000000000..6c48cf3f0e --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/EventWithLocalDateTime.java @@ -0,0 +1,29 @@ +package org.baeldung.jackson.date; + +import java.time.LocalDateTime; + +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class EventWithLocalDateTime { + public String name; + + @JsonSerialize(using = CustomLocalDateTimeSerializer.class) + public LocalDateTime eventDate; + + public EventWithLocalDateTime() { + super(); + } + + public EventWithLocalDateTime(final String name, final LocalDateTime eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public LocalDateTime getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java b/jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java new file mode 100644 index 0000000000..9cdd6a0fab --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/date/EventWithSerializer.java @@ -0,0 +1,31 @@ +package org.baeldung.jackson.date; + +import java.util.Date; + +import com.fasterxml.jackson.databind.annotation.JsonDeserialize; +import com.fasterxml.jackson.databind.annotation.JsonSerialize; + +public class EventWithSerializer { + public String name; + + @JsonDeserialize(using = CustomDateDeserializer.class) + @JsonSerialize(using = CustomDateSerializer.class) + public Date eventDate; + + public EventWithSerializer() { + super(); + } + + public EventWithSerializer(final String name, final Date eventDate) { + this.name = name; + this.eventDate = eventDate; + } + + public Date getEventDate() { + return eventDate; + } + + public String getName() { + return name; + } +} diff --git a/jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java b/jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java new file mode 100644 index 0000000000..42980baa18 --- /dev/null +++ b/jackson/src/test/java/org/baeldung/jackson/test/JacksonDateTest.java @@ -0,0 +1,143 @@ +package org.baeldung.jackson.test; + +import static org.hamcrest.Matchers.containsString; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import java.io.IOException; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.time.LocalDateTime; +import java.util.Date; +import java.util.TimeZone; + +import org.baeldung.jackson.date.Event; +import org.baeldung.jackson.date.EventWithFormat; +import org.baeldung.jackson.date.EventWithJodaTime; +import org.baeldung.jackson.date.EventWithLocalDateTime; +import org.baeldung.jackson.date.EventWithSerializer; +import org.joda.time.DateTime; +import org.junit.Test; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.SerializationFeature; + +public class JacksonDateTest { + + @Test + public void whenSerializeDateWithJackson_thenSerializedToNumber() throws JsonProcessingException, ParseException { + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + + final String toParse = "01-01-1970 01:00"; + final Date date = df.parse(toParse); + final Event event = new Event("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString("3600000")); + } + + @Test + public void whenSerializeDateToISO8601_thenSerializedToText() throws JsonProcessingException, ParseException { + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + + final String toParse = "01-01-1970 02:30"; + final Date date = df.parse(toParse); + final Event event = new Event("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); + + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString("1970-01-01T02:30:00.000+0000")); + } + + @Test + public void whenSetObjectMapperDateFormat_thenCorrect() throws JsonProcessingException, ParseException { + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm"); + + final String toParse = "20-12-2014 02:30"; + final Date date = df.parse(toParse); + final Event event = new Event("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + mapper.setDateFormat(df); + + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString(toParse)); + } + + @Test + public void whenUseJsonFormatAnnotationToFormatDate_thenCorrect() throws JsonProcessingException, ParseException { + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + df.setTimeZone(TimeZone.getTimeZone("UTC")); + + final String toParse = "20-12-2014 02:30:00"; + final Date date = df.parse(toParse); + final EventWithFormat event = new EventWithFormat("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString(toParse)); + } + + @Test + public void whenUseCustomDateSerializer_thenCorrect() throws JsonProcessingException, ParseException { + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + + final String toParse = "20-12-2014 02:30:00"; + final Date date = df.parse(toParse); + final EventWithSerializer event = new EventWithSerializer("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString(toParse)); + } + + @Test + public void whenSerializeJodaTimeWithJackson_thenCorrect() throws JsonProcessingException { + final DateTime date = new DateTime(2014, 12, 20, 2, 30); + final EventWithJodaTime event = new EventWithJodaTime("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString("2014-12-20 02:30")); + } + + @Test + public void whenSerializeJava8DateWithCustomSerializer_thenCorrect() throws JsonProcessingException { + final LocalDateTime date = LocalDateTime.of(2014, 12, 20, 2, 30); + final EventWithLocalDateTime event = new EventWithLocalDateTime("party", date); + + final ObjectMapper mapper = new ObjectMapper(); + final String result = mapper.writeValueAsString(event); + assertThat(result, containsString("2014-12-20 02:30")); + } + + @Test + public void whenDeserializeDateWithJackson_thenCorrect() throws JsonProcessingException, IOException { + final String json = "{\"name\":\"party\",\"eventDate\":\"20-12-2014 02:30:00\"}"; + + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + final ObjectMapper mapper = new ObjectMapper(); + mapper.setDateFormat(df); + + final Event event = mapper.reader(Event.class).readValue(json); + assertEquals("20-12-2014 02:30:00", df.format(event.eventDate)); + } + + @Test + public void whenDeserializeDateUsingCustomDeserializer_thenCorrect() throws JsonProcessingException, IOException { + final String json = "{\"name\":\"party\",\"eventDate\":\"20-12-2014 02:30:00\"}"; + + final SimpleDateFormat df = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss"); + final ObjectMapper mapper = new ObjectMapper(); + + final EventWithSerializer event = mapper.reader(EventWithSerializer.class).readValue(json); + assertEquals("20-12-2014 02:30:00", df.format(event.eventDate)); + } + +} diff --git a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java index fe73f719bf..999f890ebb 100644 --- a/spring-rest/src/main/java/org/baeldung/config/WebConfig.java +++ b/spring-rest/src/main/java/org/baeldung/config/WebConfig.java @@ -1,10 +1,12 @@ package org.baeldung.config; +import java.text.SimpleDateFormat; import java.util.List; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; import org.springframework.http.converter.xml.MarshallingHttpMessageConverter; import org.springframework.oxm.xstream.XStreamMarshaller; @@ -25,7 +27,12 @@ public class WebConfig extends WebMvcConfigurerAdapter { @Override public void configureMessageConverters(final List> messageConverters) { messageConverters.add(createXmlHttpMessageConverter()); - messageConverters.add(new MappingJackson2HttpMessageConverter()); + // messageConverters.add(new MappingJackson2HttpMessageConverter()); + + final Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder(); + builder.indentOutput(true).dateFormat(new SimpleDateFormat("dd-MM-yyyy hh:mm")); + messageConverters.add(new MappingJackson2HttpMessageConverter(builder.build())); + // messageConverters.add(new MappingJackson2XmlHttpMessageConverter(builder.createXmlMapper(true).build())); super.configureMessageConverters(messageConverters); } diff --git a/spring-rest/src/main/java/org/baeldung/web/controller/ItemController.java b/spring-rest/src/main/java/org/baeldung/web/controller/ItemController.java index 3c06dd4129..cfde4b23b1 100644 --- a/spring-rest/src/main/java/org/baeldung/web/controller/ItemController.java +++ b/spring-rest/src/main/java/org/baeldung/web/controller/ItemController.java @@ -1,5 +1,7 @@ package org.baeldung.web.controller; +import java.util.Date; + import org.baeldung.web.dto.Item; import org.baeldung.web.dto.ItemManager; import org.baeldung.web.dto.Views; @@ -23,4 +25,9 @@ public class ItemController { public Item getItemInternal(@PathVariable final int id) { return ItemManager.getById(id); } + + @RequestMapping("/date") + public Date getCurrentDate() { + return new Date(); + } } \ No newline at end of file