Jackson and Lombok Examples
1. Introduction
Jackson is an open-source java library for processing JSONs. It deserializes a JSON string into a Plain Old Java Object (POJO) and serializes a POJO into JSON string. Each field in the JSON object corresponds to a field in the Java POJO class. Lombok is an open-source project that reduces boilerplate code by generating common methods like getters, setters, constructors, toString, equals, and hashCode at compile time. In this example, I will create a maven project which includes several Jackson and Lombok examples. The POJO will be annotated with both Jackson and Lombok annotations.
2. Setup Lombok
The Lombok library requires additional installation steps. Please follow the instructions outlined at https://projectlombok.org/setup/.
For this example, I installed the Lombok plugin at Eclipse IDE with the following steps:
- download the
lombok.jarfrom https://projectlombok.org/download. - launch the lombok installer via the
javacommand. Here is mine:C:\MaryTools\jdk-17\bin>java -jar c:\Users\azpm0\Downloads\lombok.jar. - click the “Install/Update” button to complete the installation after the Lombok installer is launched.
- restart the Eclipse IDE and verify that the Lombok is installed by viewing the “About Eclipse IDE” page as it should include “Lombok {version} is installed”. Note, the {version} may be different from the screenshot here.
3. Maven Project
In this example, I will create a pom.xml which includes Jackson, Lombok, and Junit dependencies.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>org.zheng.demo</groupId> <artifactId>jackson-lombok</artifactId> <version>0.0.1-SNAPSHOT</version> <dependencies> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.17.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-annotations --> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-annotations</artifactId> <version>2.17.1</version> </dependency> <dependency> <groupId>org.junit.jupiter</groupId> <artifactId>junit-jupiter-api</artifactId> <version>5.10.2</version> <scope>test</scope> </dependency> <!-- https://mvnrepository.com/artifact/org.projectlombok/lombok --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.32</version> <scope>provided</scope> </dependency> </dependencies> </project>
4. POJOs
In this step, I will create three POJOs and will be used at step 5.
4.1 Order Object
In this example, I will create an Order.java which includes two data members.
productName– the optional product name.quantity– the optional quantity value.
Order.java
package org.zheng.demo.data;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
@JsonIgnoreProperties(ignoreUnknown = true)
public class Order {
private String productName;
private int quantity;
}
- Line 10: the Lombok
@Dataannotation combines@Getter,@Setter,@ToString,@EqualsAndHashCode, and@NoArgsConstructortogether. - Line 11, 12: The Lombok
@AllArgsConstructorand@NoArgsConstructor. Please note that@NoArgsConstructoris needed for Jackson POJO objects. - Line 13: the Lombok
@Buildergenerates builder creation. - Line 14: the Jackson
@JsonIgnoreProperties(ignoreUnknown = true)ignores unknown properties.
You can confirm that the getters, setters, default contructors, equals, hashCode, and toString methods are generated by viewing the Order's outline as the following screenshot.
4.2 Customer Object
In this example, I will create a Customer.java which has five private data members and one method.
custTag– an optional customer’s tag.email– an optional customer’s email address.id– a unique identifier.name– a mandatory name field.orders– an optional list of orders belong to this customer.addOrder() – this method adds an order to its orders list. Note: it uses theloggenerated by the@Logannotation.
Customer.java
package org.zheng.demo.data;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.java.Log;
@Data
@NoArgsConstructor
@RequiredArgsConstructor
@Log
@JsonIgnoreProperties(ignoreUnknown = true)
public class Customer implements Serializable {
private static final long serialVersionUID = 5963349342478710542L;
private String custTag;
private String email;
private int id;
@NonNull
private String name;
private List<Order> orders;
public void addOrder(Order order) {
log.info("addOrder starts for "+ order.toString());
if (this.orders == null) {
this.orders = new ArrayList<>();
}
this.orders.add(order);
}
}
- Line 15: the Lombok
@Dataannotation combines@Getter, @Setter,@ToString,@EqualsAndHashCode, and@NoArgsConstructortogether. - Line 16: the Lombok
@NoArgsConstructorgenerates a no-arguments constructor. - Line 17: the Lombok
@RequiredArgsConstructorgenerates a constructor for required fields (final fields and fields marked with@NonNull). - Line 18: the Lombok @Log generates a
java.util.logging.Loggerfield with field name aslog. - Line 19: the Jackson
@JsonIgnoreProperties(ignoreUnknown = true)ignores unknown properties. - Line 28: the Lombok
@Nonnullmarks the field as non-null value. - Line 33: log the message via the
logfield generated from the Lombok @Log.
4.3 Phone Object
In this example, I will create a Phone.java which contains three data members.
countryCode– an optional country code.number– an optional phone number.notInJson– an optional phone data which annotates with@JsonIgnoreto ignore during the JSON processing.
Phone.java
package org.zheng.demo.data;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
@Data
public class Phone {
private String countryCode;
@JsonIgnore
private String notInJson;
private String number;
}
- Line 7: the Lombok
@Dataannotation combines@Getter,@Setter,@ToString,@EqualsAndHashCode, and@NoArgsConstructortogether. - Line 11:
@JsonIgnoreignores thenotInJsonfield.
5. Demo with Junit Tests
In this example, I will create a JacksonLombokTest.java which has two tests.
test_customer– first it creates acustomerobject via the constructor and setters generated from Lombok@Data,@RequiredArgsConstructor,@NoArgsConstructor,@AllArgsConstructor, and@Builder. Then it serializes thecustomerobject into a JSON string, Lastly, it deserializes the JSON string back to the customer object and verifies it is the same as the originalcustomerobject via theequalsmethod generated from Lombok.test_phone– first it creates aphoneobject via the constructor and setter generated from lombok@Data. Then it serializes thephoneobject into a JSON string, Lastly, it deserializes the JSON string back to the phone object and verifies it is NOT same as the originalphoneobject via theequalsmethod generated from Lombok because the field notInJson is marked with@JsonIgnore.
JacksonLombokTest.java
package org.zheng.demo;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertFalse;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.junit.jupiter.api.Assertions.assertTrue;
import org.junit.jupiter.api.Test;
import org.zheng.demo.data.Customer;
import org.zheng.demo.data.Order;
import org.zheng.demo.data.Phone;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
class JacksonLombokTest {
private ObjectMapper ob = new ObjectMapper();
@Test
void test_customer() {
Customer customer = new Customer("Zheng");
customer.setCustTag("major");
customer.setId(2);
customer.setEmail("[email protected]");
Order order = new Order("test", 10);
customer.addOrder(order);
Order order2 = Order.builder().productName("PS").quantity(20).build();
customer.addOrder(order2);
try {
String jsonStr = ob.writerWithDefaultPrettyPrinter().writeValueAsString(customer);
System.out.println(jsonStr);
Customer readCust = ob.readValue(jsonStr, Customer.class);
assertTrue(customer.equals(readCust));
assertEquals("major", readCust.getCustTag());
assertEquals("[email protected]", readCust.getEmail());
assertEquals("Zheng", readCust.getName());
assertEquals(2, readCust.getId());
assertEquals(2, readCust.getOrders().size());
assertEquals("test", readCust.getOrders().get(0).getProductName());
assertEquals(10, readCust.getOrders().get(0).getQuantity());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
@Test
void test_phone() {
Phone phone = new Phone();
phone.setCountryCode("001");
phone.setNotInJson("notInJson");
phone.setNumber("314-123-4567");
String jsonStr;
try {
jsonStr = ob.writeValueAsString(phone);
Phone readPhone = ob.readValue(jsonStr, Phone.class);
assertFalse(readPhone.equals(phone));
assertNull(readPhone.getNotInJson());
assertNotNull(phone.getNotInJson());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
}
- Line 23: the
customer(name)constructor is generated from@RequiredArgsConstructor. - Line 24 – 25: the customer’s setters are generated from
@Data. - Line 27: the
order(productName, quantity)constructor is generated fromAllArgsConstructor. - Line 29 create an order object via the generated static
buildermethod. - Line 33: serialize the customer object into a JSON string.
- Line 36: deserialize the JSON string into a new customer object.
- Line 38 – 44: verify the data via the generated getters from Lombok.
- Line 53-56: create a phone object via the generated constructor and setters.
- Line 60, 61: serialize the phone object into JSON and deserialize the JSON into a new phone object.
- Line 62, 63: verify the data via the generated getters from Lombok. Please note, the generated phone is different from the original phone as it has an ignored field.
Execute the Junit test and capture the output.
JacksonLombokTest output
May 30, 2024 7:00:22 AM org.zheng.demo.data.Customer addOrder
INFO: addOrder starts for Order(productName=test, quantity=10)
May 30, 2024 7:00:22 AM org.zheng.demo.data.Customer addOrder
INFO: addOrder starts for Order(productName=PS, quantity=20)
{
"custTag" : "major",
"email" : "[email protected]",
"id" : 2,
"name" : "Zheng",
"orders" : [ {
"productName" : "test",
"quantity" : 10
}, {
"productName" : "PS",
"quantity" : 20
} ]
}
- Line 1-4: the log statements added by the generated
logfield when theaddOrdermethod is called.
6. Conclusion
As you see in the Jackson and Lombok examples, the Jackson and Lombok annotations help writing cleaner and more maintainable code. Jackson provides annotations to map the POJO fields to JSON and Lombok provides annotations to reduce boilerplate code.
7. Download
This was a maven project which includes both Jackson and Lombok examples to process JSON string while reducing boilerplate code.
You can download the full source code of this example here: Jackson and Lombok Examples



