Using Jackson ObjectMapper with Jersey
Categories:
Seamless JSON Handling: Integrating Jackson ObjectMapper with Jersey

Learn how to effectively configure and use Jackson ObjectMapper within your Jersey RESTful applications for robust JSON serialization and deserialization.
Jersey, a popular open-source framework for developing RESTful web services in Java, often needs to handle JSON data. While Jersey provides its own JSON processing capabilities, integrating with Jackson ObjectMapper offers a powerful and flexible solution for complex serialization and deserialization scenarios. This article will guide you through setting up Jackson with Jersey, configuring custom mappers, and troubleshooting common issues.
Understanding the Need for Jackson in Jersey
By default, Jersey can handle basic JSON marshalling and unmarshalling. However, for advanced use cases such as custom date formats, ignoring specific fields, polymorphic type handling, or integrating with other libraries, Jackson provides a much richer feature set. Jackson's ObjectMapper
is the central class for performing these operations, offering extensive configuration options through its SerializationFeature
and DeserializationFeature
enums, as well as custom modules.
flowchart TD A[Client Request] --> B[Jersey Resource] B --> C{JSON Data} C --> D[Jackson ObjectMapper] D --> E[Java Object] E --> F[Business Logic] F --> G[Java Object] G --> H[Jackson ObjectMapper] H --> I{JSON Data} I --> J[Jersey Response] J --> K[Client Response]
Data Flow with Jackson ObjectMapper in a Jersey Application
Setting Up Jackson with Jersey
To enable Jackson for JSON processing in your Jersey application, you need to include the necessary dependencies and register the Jackson feature. Jersey provides a convenient JacksonFeature
that automatically registers the JacksonJsonProvider
.
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>2.35</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.0</version>
</dependency>
Maven Dependencies for Jersey and Jackson
Once the dependencies are in place, you need to register JacksonFeature
with your Jersey ResourceConfig
.
import org.glassfish.jersey.server.ResourceConfig;
import org.glassfish.jersey.jackson.JacksonFeature;
public class MyApplication extends ResourceConfig {
public MyApplication() {
packages("com.example.resources"); // Register your resource packages
register(JacksonFeature.class);
// Optionally, register a custom ObjectMapper provider
// register(new MyObjectMapperProvider());
}
}
Registering JacksonFeature in Jersey ResourceConfig
Customizing Jackson ObjectMapper
For more fine-grained control over JSON processing, you can provide your own ObjectMapper
instance. This is typically done by creating a custom ContextResolver<ObjectMapper>
that Jersey will discover and use. This allows you to configure serialization/deserialization features, register modules, and set custom date formats.
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;
@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {
final ObjectMapper defaultObjectMapper;
public MyObjectMapperProvider() {
defaultObjectMapper = createDefaultMapper();
}
@Override
public ObjectMapper getContext(Class<?> type) {
return defaultObjectMapper;
}
private static ObjectMapper createDefaultMapper() {
final ObjectMapper mapper = new ObjectMapper();
// Enable pretty printing for better readability in development
mapper.enable(SerializationFeature.INDENT_OUTPUT);
// Disable writing dates as timestamps
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
// Register Java 8 Date/Time module
mapper.registerModule(new JavaTimeModule());
// Ignore unknown properties to prevent deserialization errors
// mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return mapper;
}
}
Custom ObjectMapper Provider for Jersey
MyObjectMapperProvider
in your ResourceConfig
if you create one, as shown in the commented line in the MyApplication
example. If you don't register it explicitly, Jersey's JacksonFeature
might still use its default ObjectMapper
.Example Jersey Resource with JSON
With Jackson configured, your Jersey resources can now seamlessly consume and produce JSON data using standard JAX-RS annotations like @Consumes
and @Produces
.
import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import java.time.LocalDateTime;
@Path("/products")
@Produces(MediaType.APPLICATION_JSON)
@Consumes(MediaType.APPLICATION_JSON)
public class ProductResource {
@GET
@Path("/{id}")
public Product getProduct(long id) {
// In a real application, fetch from a database
return new Product(id, "Example Product", 19.99, LocalDateTime.now());
}
@POST
public Response createProduct(Product product) {
// In a real application, save to a database
System.out.println("Received product: " + product.getName());
return Response.status(Response.Status.CREATED).entity(product).build();
}
}
class Product {
private long id;
private String name;
private double price;
private LocalDateTime creationDate;
// Constructors, getters, and setters
public Product() {}
public Product(long id, String name, double price, LocalDateTime creationDate) {
this.id = id;
this.name = name;
this.price = price;
this.creationDate = creationDate;
}
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 LocalDateTime getCreationDate() { return creationDate; }
public void setCreationDate(LocalDateTime creationDate) { this.creationDate = creationDate; }
@Override
public String toString() {
return "Product{id=" + id + ", name='" + name + '\'' + ", price=" + price + ", creationDate=" + creationDate + '}';
}
}
Jersey Resource and Product POJO for JSON interaction
LocalDateTime
and other Java 8 Date/Time API types to be correctly serialized/deserialized, ensure you have the jackson-datatype-jsr310
dependency and register JavaTimeModule
with your ObjectMapper
.