www.baeldung.com
Open in
urlscan Pro
172.66.43.8
Public Scan
Submitted URL: http://www.baeldung.com/jackson-optional
Effective URL: https://www.baeldung.com/jackson-optional
Submission: On August 09 via manual from GB — Scanned from US
Effective URL: https://www.baeldung.com/jackson-optional
Submission: On August 09 via manual from GB — Scanned from US
Form analysis
0 forms found in the DOMText Content
* * * Start Here * Courses ▼▲ * REST WITH SPRING BOOT The canonical reference for building a production grade API with Spring * LEARN SPRING SECURITY ▼▲ THE unique Spring Security education if you’re working with Java today * LEARN SPRING SECURITY CORE Focus on the Core of Spring Security 6 * LEARN SPRING SECURITY OAUTH Focus on the new OAuth2 stack in Spring Security 6 * LEARN SPRING From no experience to actually building stuff * LEARN SPRING DATA JPA The full guide to persistence with Spring Data JPA * Guides ▼▲ * PERSISTENCE The Persistence with Spring guides * REST The guides on building REST APIs with Spring * SECURITY The Spring Security guides * About ▼▲ * FULL ARCHIVE The high level overview of all the articles on the site. * BAELDUNG EBOOKS Discover all of our eBooks * ABOUT BAELDUNG About Baeldung. * WRITE FOR BAELDUNG Become a writer on the site. * * 1. 1. Introduction 2. 2. Problem Overview 1. 2.1. Maven Dependency 2. 2.2. Our Book Object 3. 2.3. Serialization 4. 2.4. Deserialization 3. 3. Solution 1. 3.1. Maven Dependency and Registration 2. 3.2. Serialization 3. 3.3. Deserialization 4. 4. Conclusion USING OPTIONAL WITH JACKSON Powered By 00:06/08:08 10 Sec 80.5M 133 Spring Security - Remember Me with Persistence (LSS - Module 3 - Lesson 3) Next Stay Last updated: August 18, 2023 Written by: baeldung * Data * Jackson * Jackson Basics * Java Null * Optional 1. INTRODUCTION In this article, we’ll give an overview of the Optional class, and then explain some problems that we might run into when using it with Jackson. Following this, we’ll introduce a solution which will get Jackson to treat Optionals as if they were ordinary nullable objects. 2. PROBLEM OVERVIEW First, let’s take a look at what happens when we try to serialize and deserialize Optionals with Jackson. 2.1. MAVEN DEPENDENCY To use Jackson, let’s make sure we’re using its latest version: <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-core</artifactId> <version>2.17.2</version> </dependency>Copy 2.2. OUR BOOK OBJECT Then, let’s create a class Book, containing one ordinary and one Optional field: public class Book { String title; Optional<String> subTitle; // getters and setters omitted }Copy Keep in mind that Optionals should not be used as fields and we are doing this to illustrate the problem. 2.3. SERIALIZATION Now, let’s instantiate a Book: Book book = new Book(); book.setTitle("Oliver Twist"); book.setSubTitle(Optional.of("The Parish Boy's Progress"));Copy And finally, let’s try serializing it using a Jackson ObjectMapper: String result = mapper.writeValueAsString(book);Copy We’ll see that the output of the Optional field, does not contain its value, but instead a nested JSON object with a field called present: {"title":"Oliver Twist","subTitle":{"present":true}}Copy Although this may look strange, it’s actually what we should expect. In this case, isPresent() is a public getter on the Optional class. This means it will be serialized with a value of true or false, depending on whether it is empty or not. This is Jackson’s default serialization behavior. If we think about it, what we want is for actual the value of the subtitle field to be serialized. 2.4. DESERIALIZATION Now, let’s reverse our previous example, this time trying to deserialize an object into an Optional. We’ll see that now we get a JsonMappingException: @Test(expected = JsonMappingException.class) public void givenFieldWithValue_whenDeserializing_thenThrowException String bookJson = "{ \"title\": \"Oliver Twist\", \"subTitle\": \"foo\" }"; Book result = mapper.readValue(bookJson, Book.class); } Copy Let’s view the stack trace: com.fasterxml.jackson.databind.JsonMappingException: Can not construct instance of java.util.Optional: no String-argument constructor/factory method to deserialize from String value ('The Parish Boy's Progress')Copy This behavior again makes sense. Essentially, Jackson needs a constructor which can take the value of subtitle as an argument. This is not the case with our Optional field. 3. SOLUTION What we want, is for Jackson to treat an empty Optional as null, and to treat a present Optional as a field representing its value. Fortunately, this problem has been solved for us. Jackson has a set of modules that deal with JDK 8 datatypes, including Optional. 3.1. MAVEN DEPENDENCY AND REGISTRATION First, let’s add the latest version as a Maven dependency: <dependency> <groupId>com.fasterxml.jackson.datatype</groupId> <artifactId>jackson-datatype-jdk8</artifactId> <version>2.13.3</version> </dependency>Copy Now, all we need to do is register the module with our ObjectMapper: ObjectMapper mapper = new ObjectMapper(); mapper.registerModule(new Jdk8Module());Copy 3.2. SERIALIZATION Now, let’s test it. If we try and serialize our Book object again, we’ll see that there is now a subtitle, as opposed to a nested JSON: Book book = new Book(); book.setTitle("Oliver Twist"); book.setSubTitle(Optional.of("The Parish Boy's Progress")); String serializedBook = mapper.writeValueAsString(book); assertThat(from(serializedBook).getString("subTitle")) .isEqualTo("The Parish Boy's Progress");Copy If we try serializing an empty book, it will be stored as null: book.setSubTitle(Optional.empty()); String serializedBook = mapper.writeValueAsString(book); assertThat(from(serializedBook).getString("subTitle")).isNull();Copy 3.3. DESERIALIZATION Now, let’s repeat our tests for deserialization. If we reread our Book, we’ll see that we no longer get a JsonMappingException: Book newBook = mapper.readValue(result, Book.class); assertThat(newBook.getSubTitle()).isEqualTo(Optional.of("The Parish Boy's Progress"));Copy Finally, let’s repeat the test again, this time with null. We’ll see that yet again we don’t get a JsonMappingException, and in fact, have an empty Optional: assertThat(newBook.getSubTitle()).isEqualTo(Optional.empty());Copy 4. CONCLUSION We’ve shown how to get around this problem by leveraging the JDK 8 DataTypes module, demonstrating how it enables Jackson to treat an empty Optional as null, and a present Optional as an ordinary field. The implementation of these examples can be found over on GitHub; this is a Maven-based project, so should be easy to run as is. Course – LS – NPI (cat=JSON/Jackson) Get started with Spring Boot and with core Spring, through the Learn Spring course: >> CHECK OUT THE COURSE res – Jackson (eBook) (cat=Jackson) Do JSON right with Jackson Download the E-book eBook – Jackson – NPI (cat=Jackson) Do JSON right with Jackson Download the E-book COURSES * All Courses * All Bulk Courses * All Bulk Team Courses * The Courses Platform SERIES * Java “Back to Basics” Tutorial * Jackson JSON Tutorial * Apache HttpClient Tutorial * REST with Spring Tutorial * Spring Persistence Tutorial * Security with Spring * Spring Reactive Tutorials ABOUT * About Baeldung * The Full Archive * Editors * Our Partners * Partner with Baeldung * eBooks * Terms of Service * Privacy Policy * Company Info * Contact Freestar.com