diff --git a/spring-boot-modules/pom.xml b/spring-boot-modules/pom.xml index fa70a9f058..3d721d7147 100644 --- a/spring-boot-modules/pom.xml +++ b/spring-boot-modules/pom.xml @@ -68,6 +68,7 @@ spring-boot-vue spring-boot-xml spring-boot-actuator + spring-boot-jackson diff --git a/spring-boot-modules/spring-boot-jackson/pom.xml b/spring-boot-modules/spring-boot-jackson/pom.xml new file mode 100644 index 0000000000..b502bca908 --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/pom.xml @@ -0,0 +1,21 @@ + + + + parent-boot-2 + com.baeldung + 0.0.1-SNAPSHOT + ../../parent-boot-2 + + 4.0.0 + + spring-boot-jackson + + + org.springframework.boot + spring-boot-starter-web + + + + \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/Application.java b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/Application.java new file mode 100644 index 0000000000..c4de34879f --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/Application.java @@ -0,0 +1,12 @@ +package com.baeldung.boot.jackson; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/config/CoffeeConfiguration.java b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/config/CoffeeConfiguration.java new file mode 100644 index 0000000000..ac7be062c2 --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/config/CoffeeConfiguration.java @@ -0,0 +1,43 @@ +package com.baeldung.boot.jackson.config; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule; +import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; +import org.springframework.boot.autoconfigure.jackson.Jackson2ObjectMapperBuilderCustomizer; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Primary; +import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder; + +import java.time.format.DateTimeFormatter; + +@Configuration +public class CoffeeConfiguration { + public static final String dateTimeFormat = "dd-MM-yyyy HH:mm"; + private LocalDateTimeSerializer localDateTimeSerializer = new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(dateTimeFormat)); + + @Bean + public Jackson2ObjectMapperBuilderCustomizer jsonCustomizer() { + return builder -> builder.serializationInclusion(JsonInclude.Include.NON_NULL) + .serializers(localDateTimeSerializer); + } + + @Bean + @Primary + public ObjectMapper objectMapper() { + JavaTimeModule module = new JavaTimeModule(); + module.addSerializer(localDateTimeSerializer); + return new ObjectMapper() + .setSerializationInclusion(JsonInclude.Include.NON_NULL) + .registerModule(module); + } + + @Bean + @Primary + public Jackson2ObjectMapperBuilder jackson2ObjectMapperBuilder() { + return new Jackson2ObjectMapperBuilder() + .serializers(localDateTimeSerializer) + .serializationInclusion(JsonInclude.Include.NON_NULL); + } +} diff --git a/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java new file mode 100644 index 0000000000..2a0f6e1240 --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/controller/CoffeeController.java @@ -0,0 +1,25 @@ +package com.baeldung.boot.jackson.controller; + +import com.baeldung.boot.jackson.model.Coffee; +import com.baeldung.boot.jackson.model.CoffeeResponse; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.time.LocalDateTime; + +@RestController +public class CoffeeController { + + @GetMapping("/coffee") + public CoffeeResponse createCoffee(@RequestParam(required = false) String brand, + @RequestParam(required = false) String name) { + Coffee coffee = new Coffee() + .setBrand(brand) + .setName(name); + + return new CoffeeResponse() + .setDate(LocalDateTime.now()) + .setBody(coffee); + } +} diff --git a/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/Coffee.java b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/Coffee.java new file mode 100644 index 0000000000..12c2e200df --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/Coffee.java @@ -0,0 +1,26 @@ +package com.baeldung.boot.jackson.model; + +public class Coffee { + + private String name; + + private String brand; + + public String getName() { + return name; + } + + public Coffee setName(String name) { + this.name = name; + return this; + } + + public String getBrand() { + return brand; + } + + public Coffee setBrand(String brand) { + this.brand = brand; + return this; + } +} diff --git a/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/CoffeeResponse.java b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/CoffeeResponse.java new file mode 100644 index 0000000000..c2667df03a --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/java/com/baeldung/boot/jackson/model/CoffeeResponse.java @@ -0,0 +1,28 @@ +package com.baeldung.boot.jackson.model; + +import java.time.LocalDateTime; + +public class CoffeeResponse { + + private LocalDateTime date; + + private T body; + + public LocalDateTime getDate() { + return date; + } + + public CoffeeResponse setDate(LocalDateTime date) { + this.date = date; + return this; + } + + public T getBody() { + return body; + } + + public CoffeeResponse setBody(T body) { + this.body = body; + return this; + } +} diff --git a/spring-boot-modules/spring-boot-jackson/src/main/resources/application.properties b/spring-boot-modules/spring-boot-jackson/src/main/resources/application.properties new file mode 100644 index 0000000000..2129762424 --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/main/resources/application.properties @@ -0,0 +1,3 @@ +spring.jackson.default-property-inclusion=non_null +spring.jackson.serialization.write-dates-as-timestamps=false +spring.jackson.date-format=dd-MM-yyyy HH:mm \ No newline at end of file diff --git a/spring-boot-modules/spring-boot-jackson/src/test/java/com/baeldung/boot/jackson/CoffeeIntegrationTest.java b/spring-boot-modules/spring-boot-jackson/src/test/java/com/baeldung/boot/jackson/CoffeeIntegrationTest.java new file mode 100644 index 0000000000..d508ee45d1 --- /dev/null +++ b/spring-boot-modules/spring-boot-jackson/src/test/java/com/baeldung/boot/jackson/CoffeeIntegrationTest.java @@ -0,0 +1,32 @@ +package com.baeldung.boot.jackson; + +import com.baeldung.boot.jackson.config.CoffeeConfiguration; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.web.client.TestRestTemplate; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; + +import static org.assertj.core.api.Assertions.assertThat; + +@SpringBootTest(classes = Application.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +public class CoffeeIntegrationTest { + + @Autowired + TestRestTemplate restTemplate; + + @Test + public void whenQueryCoffeeWithoutParam_thenNullIsNotInserted() { + String formattedDate = DateTimeFormatter.ofPattern(CoffeeConfiguration.dateTimeFormat) + .format(LocalDateTime.now()); + String brand = "Lavazza"; + + String url = "/coffee?brand=" + brand; + String response = restTemplate.getForObject(url, String.class); + + assertThat(response).isEqualTo( + "{\"date\":\"" + formattedDate + "\",\"body\":{\"brand\":\"" + brand + "\"}}"); + } +}