Jackson is the most popular JSON processing library for Java, providing fast, flexible, and powerful capabilities for converting between Java objects and JSON. It's the default JSON processor in Spring Framework and widely used across the Java ecosystem.
Dependencies Setup
Maven Dependencies
<properties>
<jackson.version>2.16.1</jackson.version>
</properties>
<dependencies>
<!-- Core Jackson -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- Jackson Modules -->
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jsr310</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.datatype</groupId>
<artifactId>jackson-datatype-jdk8</artifactId>
<version>${jackson.version}</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-parameter-names</artifactId>
<version>${jackson.version}</version>
</dependency>
<!-- For JSON Schema -->
<dependency>
<groupId>com.fasterxml.jackson.module</groupId>
<artifactId>jackson-module-jsonSchema</artifactId>
<version>${jackson.version}</version>
</dependency>
</dependencies>
Basic ObjectMapper Usage
Example 1: Basic Serialization and Deserialization
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import java.time.LocalDate;
import java.util.List;
import java.util.Map;
public class BasicJacksonExample {
private static final ObjectMapper objectMapper = new ObjectMapper()
.registerModule(new JavaTimeModule())
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
static class User {
private Long id;
private String name;
private String email;
private LocalDate birthDate;
private List<String> roles;
// Constructors
public User() {}
public User(Long id, String name, String email, LocalDate birthDate, List<String> roles) {
this.id = id;
this.name = name;
this.email = email;
this.birthDate = birthDate;
this.roles = roles;
}
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public LocalDate getBirthDate() { return birthDate; }
public void setBirthDate(LocalDate birthDate) { this.birthDate = birthDate; }
public List<String> getRoles() { return roles; }
public void setRoles(List<String> roles) { this.roles = roles; }
@Override
public String toString() {
return String.format("User{id=%d, name='%s', email='%s', birthDate=%s, roles=%s}",
id, name, email, birthDate, roles);
}
}
public static void main(String[] args) throws Exception {
User user = new User(1L, "John Doe", "[email protected]",
LocalDate.of(1990, 5, 15),
List.of("ADMIN", "USER"));
// Serialize to JSON
String json = objectMapper.writeValueAsString(user);
System.out.println("Serialized JSON:");
System.out.println(json);
// Pretty print
String prettyJson = objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(user);
System.out.println("\nPretty JSON:");
System.out.println(prettyJson);
// Deserialize from JSON
String jsonInput = """
{
"id": 2,
"name": "Jane Smith",
"email": "[email protected]",
"birthDate": "1985-08-20",
"roles": ["USER"]
}
""";
User deserializedUser = objectMapper.readValue(jsonInput, User.class);
System.out.println("\nDeserialized User:");
System.out.println(deserializedUser);
// Working with Map
Map<String, Object> userMap = objectMapper.readValue(jsonInput, Map.class);
System.out.println("\nAs Map:");
System.out.println(userMap);
// Working with List
String usersJson = """
[
{"id": 1, "name": "John Doe", "email": "[email protected]"},
{"id": 2, "name": "Jane Smith", "email": "[email protected]"}
]
""";
List<User> users = objectMapper.readValue(usersJson,
objectMapper.getTypeFactory().constructCollectionType(List.class, User.class));
System.out.println("\nUser List:");
users.forEach(System.out::println);
}
}
Jackson Annotations
Example 2: Using Jackson Annotations
import com.fasterxml.jackson.annotation.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.time.LocalDateTime;
import java.util.List;
public class JacksonAnnotationsExample {
@JsonInclude(JsonInclude.Include.NON_NULL)
@JsonPropertyOrder({"userId", "username", "email", "createdAt"})
static class AnnotatedUser {
@JsonProperty("userId")
private Long id;
private String username;
@JsonIgnore
private String password;
private String email;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private LocalDateTime createdAt;
@JsonUnwrapped
private Address address;
@JsonView(Views.Public.class)
private List<String> roles;
@JsonView(Views.Internal.class)
private String internalNote;
// Constructors
public AnnotatedUser() {}
public AnnotatedUser(Long id, String username, String password, String email,
LocalDateTime createdAt, Address address, List<String> roles) {
this.id = id;
this.username = username;
this.password = password;
this.email = email;
this.createdAt = createdAt;
this.address = address;
this.roles = roles;
}
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getUsername() { return username; }
public void setUsername(String username) { this.username = username; }
public String getPassword() { return password; }
public void setPassword(String password) { this.password = password; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public LocalDateTime getCreatedAt() { return createdAt; }
public void setCreatedAt(LocalDateTime createdAt) { this.createdAt = createdAt; }
public Address getAddress() { return address; }
public void setAddress(Address address) { this.address = address; }
public List<String> getRoles() { return roles; }
public void setRoles(List<String> roles) { this.roles = roles; }
public String getInternalNote() { return internalNote; }
public void setInternalNote(String internalNote) { this.internalNote = internalNote; }
}
static class Address {
private String street;
private String city;
private String zipCode;
public Address() {}
public Address(String street, String city, String zipCode) {
this.street = street;
this.city = city;
this.zipCode = zipCode;
}
public String getStreet() { return street; }
public void setStreet(String street) { this.street = street; }
public String getCity() { return city; }
public void setCity(String city) { this.city = city; }
public String getZipCode() { return zipCode; }
public void setZipCode(String zipCode) { this.zipCode = zipCode; }
}
static class Views {
static class Public {}
static class Internal extends Public {}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
Address address = new Address("123 Main St", "New York", "10001");
AnnotatedUser user = new AnnotatedUser(1L, "johndoe", "secret123", "[email protected]",
LocalDateTime.now(), address, List.of("ADMIN", "USER"));
user.setInternalNote("This is an internal note");
// Serialize with public view
String publicJson = mapper.writerWithView(Views.Public.class)
.writeValueAsString(user);
System.out.println("Public View:");
System.out.println(publicJson);
// Serialize with internal view
String internalJson = mapper.writerWithView(Views.Internal.class)
.writeValueAsString(user);
System.out.println("\nInternal View:");
System.out.println(internalJson);
// Test @JsonIgnore and @JsonUnwrapped
String normalJson = mapper.writeValueAsString(user);
System.out.println("\nNormal Serialization:");
System.out.println(normalJson);
}
}
Advanced Jackson Features
Example 3: Custom Serializers and Deserializers
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.module.SimpleModule;
import java.io.IOException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
public class CustomSerializationExample {
static class Product {
private Long id;
private String name;
private Double price;
private LocalDate manufactureDate;
private Status status;
public Product() {}
public Product(Long id, String name, Double price, LocalDate manufactureDate, Status status) {
this.id = id;
this.name = name;
this.price = price;
this.manufactureDate = manufactureDate;
this.status = status;
}
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public Double getPrice() { return price; }
public void setPrice(Double price) { this.price = price; }
public LocalDate getManufactureDate() { return manufactureDate; }
public void setManufactureDate(LocalDate manufactureDate) { this.manufactureDate = manufactureDate; }
public Status getStatus() { return status; }
public void setStatus(Status status) { this.status = status; }
@Override
public String toString() {
return String.format("Product{id=%d, name='%s', price=%.2f, manufactureDate=%s, status=%s}",
id, name, price, manufactureDate, status);
}
}
enum Status {
ACTIVE, INACTIVE, DISCONTINUED
}
// Custom Serializer for LocalDate
static class LocalDateSerializer extends JsonSerializer<LocalDate> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeString(value.format(formatter));
}
}
// Custom Deserializer for LocalDate
static class LocalDateDeserializer extends JsonDeserializer<LocalDate> {
private static final DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
return LocalDate.parse(p.getValueAsString(), formatter);
}
}
// Custom Serializer for Status enum
static class StatusSerializer extends JsonSerializer<Status> {
@Override
public void serialize(Status value, JsonGenerator gen, SerializerProvider provider)
throws IOException {
gen.writeString(value.name().toLowerCase());
}
}
// Custom Deserializer for Status enum
static class StatusDeserializer extends JsonDeserializer<Status> {
@Override
public Status deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException {
String value = p.getValueAsString().toUpperCase();
return Status.valueOf(value);
}
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Register custom serializers/deserializers
SimpleModule module = new SimpleModule();
module.addSerializer(LocalDate.class, new LocalDateSerializer());
module.addDeserializer(LocalDate.class, new LocalDateDeserializer());
module.addSerializer(Status.class, new StatusSerializer());
module.addDeserializer(Status.class, new StatusDeserializer());
mapper.registerModule(module);
Product product = new Product(1L, "Laptop", 999.99,
LocalDate.of(2023, 10, 15), Status.ACTIVE);
// Serialize with custom formatting
String json = mapper.writeValueAsString(product);
System.out.println("Custom Serialized JSON:");
System.out.println(json);
// Deserialize with custom formatting
String inputJson = """
{
"id": 2,
"name": "Mouse",
"price": 25.50,
"manufactureDate": "20/09/2023",
"status": "active"
}
""";
Product deserializedProduct = mapper.readValue(inputJson, Product.class);
System.out.println("\nDeserialized Product:");
System.out.println(deserializedProduct);
}
}
Example 4: Polymorphic Type Handling
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.List;
public class PolymorphicExample {
@JsonTypeInfo(
use = JsonTypeInfo.Id.NAME,
include = JsonTypeInfo.As.PROPERTY,
property = "type"
)
@JsonSubTypes({
@JsonSubTypes.Type(value = Car.class, name = "car"),
@JsonSubTypes.Type(value = Truck.class, name = "truck"),
@JsonSubTypes.Type(value = Motorcycle.class, name = "motorcycle")
})
static abstract class Vehicle {
private String make;
private String model;
private int year;
public Vehicle() {}
public Vehicle(String make, String model, int year) {
this.make = make;
this.model = model;
this.year = year;
}
public String getMake() { return make; }
public void setMake(String make) { this.make = make; }
public String getModel() { return model; }
public void setModel(String model) { this.model = model; }
public int getYear() { return year; }
public void setYear(int year) { this.year = year; }
public abstract String getVehicleType();
}
static class Car extends Vehicle {
private int doors;
private String fuelType;
public Car() {}
public Car(String make, String model, int year, int doors, String fuelType) {
super(make, model, year);
this.doors = doors;
this.fuelType = fuelType;
}
public int getDoors() { return doors; }
public void setDoors(int doors) { this.doors = doors; }
public String getFuelType() { return fuelType; }
public void setFuelType(String fuelType) { this.fuelType = fuelType; }
@Override
public String getVehicleType() {
return "Car";
}
}
static class Truck extends Vehicle {
private double payloadCapacity;
private boolean fourWheelDrive;
public Truck() {}
public Truck(String make, String model, int year, double payloadCapacity, boolean fourWheelDrive) {
super(make, model, year);
this.payloadCapacity = payloadCapacity;
this.fourWheelDrive = fourWheelDrive;
}
public double getPayloadCapacity() { return payloadCapacity; }
public void setPayloadCapacity(double payloadCapacity) { this.payloadCapacity = payloadCapacity; }
public boolean isFourWheelDrive() { return fourWheelDrive; }
public void setFourWheelDrive(boolean fourWheelDrive) { this.fourWheelDrive = fourWheelDrive; }
@Override
public String getVehicleType() {
return "Truck";
}
}
static class Motorcycle extends Vehicle {
private String engineType;
private boolean hasSidecar;
public Motorcycle() {}
public Motorcycle(String make, String model, int year, String engineType, boolean hasSidecar) {
super(make, model, year);
this.engineType = engineType;
this.hasSidecar = hasSidecar;
}
public String getEngineType() { return engineType; }
public void setEngineType(String engineType) { this.engineType = engineType; }
public boolean isHasSidecar() { return hasSidecar; }
public void setHasSidecar(boolean hasSidecar) { this.hasSidecar = hasSidecar; }
@Override
public String getVehicleType() {
return "Motorcycle";
}
}
static class Garage {
private List<Vehicle> vehicles;
public Garage() {}
public Garage(List<Vehicle> vehicles) {
this.vehicles = vehicles;
}
public List<Vehicle> getVehicles() { return vehicles; }
public void setVehicles(List<Vehicle> vehicles) { this.vehicles = vehicles; }
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Create different types of vehicles
Vehicle car = new Car("Toyota", "Camry", 2023, 4, "Gasoline");
Vehicle truck = new Truck("Ford", "F-150", 2023, 1500.0, true);
Vehicle motorcycle = new Motorcycle("Harley-Davidson", "Sportster", 2023, "V-Twin", false);
Garage garage = new Garage(List.of(car, truck, motorcycle));
// Serialize polymorphic types
String json = mapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(garage);
System.out.println("Polymorphic JSON:");
System.out.println(json);
// Deserialize back to correct types
String inputJson = """
{
"vehicles" : [ {
"type" : "car",
"make" : "Honda",
"model" : "Civic",
"year" : 2023,
"doors" : 4,
"fuelType" : "Hybrid"
}, {
"type" : "truck",
"make" : "Chevrolet",
"model" : "Silverado",
"year" : 2023,
"payloadCapacity" : 2000.0,
"fourWheelDrive" : true
} ]
}
""";
Garage deserializedGarage = mapper.readValue(inputJson, Garage.class);
System.out.println("\nDeserialized Vehicles:");
deserializedGarage.getVehicles().forEach(vehicle -> {
System.out.println(vehicle.getVehicleType() + ": " + vehicle.getMake() + " " + vehicle.getModel());
});
}
}
Streaming API (JsonParser/JsonGenerator)
Example 5: Streaming API for Large JSON
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
public class StreamingApiExample {
static class LargeDataProcessor {
public void writeLargeJson(File file, List<User> users) throws IOException {
JsonFactory jsonFactory = new JsonFactory();
try (JsonGenerator generator = jsonFactory.createGenerator(file, JsonEncoding.UTF8)) {
generator.writeStartArray();
for (User user : users) {
generator.writeStartObject();
generator.writeNumberField("id", user.getId());
generator.writeStringField("name", user.getName());
generator.writeStringField("email", user.getEmail());
// Write roles array
generator.writeArrayFieldStart("roles");
for (String role : user.getRoles()) {
generator.writeString(role);
}
generator.writeEndArray();
generator.writeEndObject();
}
generator.writeEndArray();
}
}
public List<User> readLargeJson(File file) throws IOException {
List<User> users = new ArrayList<>();
JsonFactory jsonFactory = new JsonFactory();
try (JsonParser parser = jsonFactory.createParser(file)) {
// Advance to start array
while (parser.nextToken() != JsonToken.START_ARRAY) {
// Skip until array start
}
// Process each object in array
while (parser.nextToken() != JsonToken.END_ARRAY) {
if (parser.currentToken() == JsonToken.START_OBJECT) {
users.add(parseUser(parser));
}
}
}
return users;
}
private User parseUser(JsonParser parser) throws IOException {
User user = new User();
List<String> roles = new ArrayList<>();
while (parser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = parser.getCurrentName();
parser.nextToken(); // Move to value
switch (fieldName) {
case "id":
user.setId(parser.getLongValue());
break;
case "name":
user.setName(parser.getText());
break;
case "email":
user.setEmail(parser.getText());
break;
case "roles":
// Parse roles array
while (parser.nextToken() != JsonToken.END_ARRAY) {
roles.add(parser.getText());
}
user.setRoles(roles);
break;
}
}
return user;
}
}
static class User {
private Long id;
private String name;
private String email;
private List<String> roles;
// Constructors, getters, setters
public User() {}
public User(Long id, String name, String email, List<String> roles) {
this.id = id;
this.name = name;
this.email = email;
this.roles = roles;
}
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public String getEmail() { return email; }
public void setEmail(String email) { this.email = email; }
public List<String> getRoles() { return roles; }
public void setRoles(List<String> roles) { this.roles = roles; }
@Override
public String toString() {
return String.format("User{id=%d, name='%s', email='%s', roles=%s}",
id, name, email, roles);
}
}
public static void main(String[] args) throws Exception {
LargeDataProcessor processor = new LargeDataProcessor();
// Create sample data
List<User> users = List.of(
new User(1L, "John Doe", "[email protected]", List.of("ADMIN", "USER")),
new User(2L, "Jane Smith", "[email protected]", List.of("USER")),
new User(3L, "Bob Johnson", "[email protected]", List.of("MODERATOR", "USER"))
);
// Write using streaming API
File jsonFile = new File("users.json");
processor.writeLargeJson(jsonFile, users);
System.out.println("JSON written to: " + jsonFile.getAbsolutePath());
// Read using streaming API
List<User> readUsers = processor.readLargeJson(jsonFile);
System.out.println("\nRead users:");
readUsers.forEach(System.out::println);
// Clean up
jsonFile.delete();
}
}
Tree Model (JsonNode)
Example 6: Working with JsonNode
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.*;
import java.util.Iterator;
public class JsonNodeExample {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
// Create JSON programmatically
ObjectNode userNode = mapper.createObjectNode();
userNode.put("id", 1);
userNode.put("name", "John Doe");
userNode.put("email", "[email protected]");
userNode.put("active", true);
ArrayNode rolesNode = userNode.putArray("roles");
rolesNode.add("ADMIN");
rolesNode.add("USER");
ObjectNode addressNode = mapper.createObjectNode();
addressNode.put("street", "123 Main St");
addressNode.put("city", "New York");
addressNode.put("zipCode", "10001");
userNode.set("address", addressNode);
System.out.println("Created JSON Node:");
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(userNode));
// Parse JSON string to JsonNode
String jsonString = """
{
"id": 2,
"name": "Jane Smith",
"email": "[email protected]",
"active": true,
"roles": ["USER"],
"address": {
"street": "456 Oak Ave",
"city": "Los Angeles",
"zipCode": "90001"
}
}
""";
JsonNode parsedNode = mapper.readTree(jsonString);
// Access values
System.out.println("\nAccessing values:");
System.out.println("ID: " + parsedNode.get("id").asInt());
System.out.println("Name: " + parsedNode.get("name").asText());
System.out.println("Active: " + parsedNode.get("active").asBoolean());
// Iterate through roles
System.out.println("Roles:");
JsonNode roles = parsedNode.get("roles");
if (roles.isArray()) {
for (JsonNode role : roles) {
System.out.println(" - " + role.asText());
}
}
// Access nested object
JsonNode address = parsedNode.get("address");
System.out.println("City: " + address.get("city").asText());
// Modify JSON
((ObjectNode) parsedNode).put("name", "Jane Doe");
((ObjectNode) parsedNode).put("age", 30);
System.out.println("\nModified JSON:");
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(parsedNode));
// Search in JSON
System.out.println("\nSearching for fields containing 'name':");
searchFields(parsedNode, "name");
}
private static void searchFields(JsonNode node, String searchTerm) {
if (node.isObject()) {
Iterator<String> fieldNames = node.fieldNames();
while (fieldNames.hasNext()) {
String fieldName = fieldNames.next();
if (fieldName.toLowerCase().contains(searchTerm.toLowerCase())) {
System.out.println("Found field: " + fieldName + " = " + node.get(fieldName));
}
searchFields(node.get(fieldName), searchTerm);
}
} else if (node.isArray()) {
for (JsonNode arrayElement : node) {
searchFields(arrayElement, searchTerm);
}
}
}
}
Best Practices and Configuration
Example 7: Comprehensive ObjectMapper Configuration
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.fasterxml.jackson.module.paramnames.ParameterNamesModule;
public class ObjectMapperConfiguration {
public static ObjectMapper createConfiguredObjectMapper() {
return new ObjectMapper()
// Register modules
.registerModule(new JavaTimeModule())
.registerModule(new Jdk8Module())
.registerModule(new ParameterNamesModule())
// Serialization features
.enable(SerializationFeature.INDENT_OUTPUT)
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
.enable(SerializationFeature.WRITE_ENUMS_USING_TO_STRING)
// Deserialization features
.enable(DeserializationFeature.READ_ENUMS_USING_TO_STRING)
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(DeserializationFeature.FAIL_ON_INVALID_SUBTYPE)
.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS)
.enable(DeserializationFeature.USE_LONG_FOR_INTS);
}
public static void main(String[] args) throws Exception {
ObjectMapper mapper = createConfiguredObjectMapper();
// Test the configuration
String testJson = """
{
"id": "123", // String that should be converted to long
"price": "99.99", // String that should be converted to BigDecimal
"unknownField": "this should be ignored",
"status": "ACTIVE" // Enum as string
}
""";
TestObject obj = mapper.readValue(testJson, TestObject.class);
System.out.println("Deserialized object: " + obj);
String serialized = mapper.writeValueAsString(obj);
System.out.println("Serialized JSON: " + serialized);
}
static class TestObject {
private Long id;
private java.math.BigDecimal price;
private Status status;
// Getters and setters
public Long getId() { return id; }
public void setId(Long id) { this.id = id; }
public java.math.BigDecimal getPrice() { return price; }
public void setPrice(java.math.BigDecimal price) { this.price = price; }
public Status getStatus() { return status; }
public void setStatus(Status status) { this.status = status; }
@Override
public String toString() {
return String.format("TestObject{id=%d, price=%s, status=%s}", id, price, status);
}
}
enum Status {
ACTIVE, INACTIVE
}
}
Performance Tips
- Reuse ObjectMapper: ObjectMapper is thread-safe, create once and reuse
- Use Streaming API: For large JSON files, use JsonParser/JsonGenerator
- Enable Appropriate Features: Disable unnecessary features for performance
- Use Immutable Objects: For better performance and thread safety
- Consider Alternative JSON Libraries: For extreme performance needs, consider Jackson Afterburner or other libraries
Conclusion
Jackson is a powerful, flexible JSON processing library for Java that offers:
- High Performance: One of the fastest JSON libraries available
- Rich Feature Set: Comprehensive annotations and configuration options
- Multiple Processing Models: Object binding, tree model, and streaming API
- Excellent Spring Integration: Default JSON processor in Spring Framework
- Active Community: Well-maintained with regular updates
Whether you're building REST APIs, processing configuration files, or working with large JSON datasets, Jackson provides the tools you need for efficient JSON processing in Java.