Jackson is the most widely used JSON library in the Java ecosystem, and ObjectMapper is its workhorse. Whether you need to convert a Java object into a JSON string, parse a JSON file from disk, or read from an HTTP response body, ObjectMapper handles it all with a clean, consistent API. This guide covers everything you need to use Jackson’s ObjectMapper effectively in real projects.
What Is Jackson ObjectMapper?
ObjectMapper is the central class in Jackson’s data-binding API. It bridges the gap between Java objects (POJOs) and JSON text. Internally it uses a JsonParser for reading and a JsonGenerator for writing, but you rarely interact with those directly — ObjectMapper wraps them behind a higher-level API.
Three key facts to keep in mind:
- Thread-safe after configuration. Create one instance, share it across your application. Recreating it per request is expensive.
- Highly configurable. Date formats, null handling, unknown-property behaviour, and much more are controlled via feature flags.
- Extensible. Custom serialisers, deserialisers, and modules let you handle any type Jackson does not know about out of the box.
Adding Jackson to Your Project
The jackson-databind artifact is all you need. It pulls in jackson-core and jackson-annotations as transitive dependencies.
Maven (pom.xml):
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>3.1.2</version>
</dependency>
Gradle (build.gradle):
implementation 'com.fasterxml.jackson.core:jackson-databind:3.1.2'
If you are using Spring Boot, Jackson is already on the classpath via spring-boot-starter-web — no explicit declaration needed.
Serialising Java Objects to JSON
Serialisation converts a Java object into JSON. Consider this POJO:
public class Article {
private Long articleId;
private String title;
private List<String> tags;
// Constructors, getters, and setters
}
Write to a String:
ObjectMapper mapper = new ObjectMapper();
Article article = new Article(1L, "Jackson Deep Dive", List.of("java", "json"));
String jsonOutput = mapper.writeValueAsString(article);
System.out.println(jsonOutput);
// Output: {"articleId":1,"title":"Jackson Deep Dive","tags":["java","json"]}
Write to a File:
mapper.writeValue(new File("article.json"), article);
// Creates article.json on disk
Pretty-printed output:
String prettyJson = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(article);
/*
{
"articleId" : 1,
"title" : "Jackson Deep Dive",
"tags" : [ "java", "json" ]
}
*/
Deserialising JSON to Java Objects
Deserialisation converts JSON back into a Java object. Use readValue() and pass the target class as the second argument.
Read from a String:
String json = "{"articleId":1,"title":"Jackson Deep Dive","tags":["java","json"]}";
Article article = mapper.readValue(json, Article.class);
System.out.println(article.getTitle()); // Output: Jackson Deep Dive
Read from a File:
Article article = mapper.readValue(new File("article.json"), Article.class);
System.out.println(article.getArticleId()); // Output: 1
Read from a URL:
Article article = mapper.readValue(
new URL("https://api.example.com/articles/1"),
Article.class
);
Working with Collections and Generic Types
For generic types like List<Article>, you cannot pass List.class directly because Java erases the type parameter at runtime. Use TypeReference instead to preserve the full generic type information Jackson needs to instantiate the correct parameterised collection.
String jsonArray = "[{"articleId":1,"title":"First"},{"articleId":2,"title":"Second"}]";
List<Article> articles = mapper.readValue(
jsonArray,
new TypeReference<List<Article>>() {}
);
System.out.println(articles.size()); // Output: 2
How the Code Works
- ObjectMapper is created once and reused. Jackson scans your POJO’s getters and fields to build an internal serialisation/deserialisation model the first time a type is encountered, then caches it.
- writeValueAsString() calls the internal
JsonSerializerchain, writing each property to an in-memory buffer, then returns the completed JSON string. - readValue() tokenises the JSON input via
JsonParser, then maps each token to the corresponding field on your POJO using the cached model. - TypeReference captures the full generic type at compile time (via an anonymous subclass), giving Jackson the information it needs to instantiate the correct parameterised type at runtime.
Essential ObjectMapper Configuration Options
Raw ObjectMapper defaults are strict. Most real projects need at least a few of these tweaks:
ObjectMapper mapper = new ObjectMapper()
// Do not fail when JSON has fields your POJO does not declare
.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
// Serialise Java 8 dates correctly (requires jackson-datatype-jsr310)
.registerModule(new JavaTimeModule())
// Write dates as ISO-8601 strings, not numeric timestamps
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// Skip null fields during serialisation
.setSerializationInclusion(JsonInclude.Include.NON_NULL);
Sample Output
Given an Article object with articleId=1, title="Jackson Deep Dive", tags=["java","json"], and a null author field, the mapper configured with NON_NULL produces:
{"articleId":1,"title":"Jackson Deep Dive","tags":["java","json"]}
The author field is absent because it was null and the mapper was told to skip nulls. Without that setting, the output would include "author":null.
See Also
- Part 2: Jackson with Java Records and Optionals
- Part 3: Jackson Annotations Cheat Sheet
- Part 4: Custom Serialisers and Mix-ins
- Part 5: Polymorphic Deserialisation
- Part 6: Streaming API and JsonNode
- Part 7: Jackson Security and Best Practices
AI Prompts for Jackson ObjectMapper
Generate POJO Round-Trip Code
I have this POJO class: [paste your class here]. I am using Jackson 3.1.2. Generate five working examples using JsonMapper.builder().build(): serialise an instance to a String, serialise to a File, serialise to an OutputStream, deserialise from a String, and deserialise from an InputStream. For any LocalDate or Optional fields, confirm no extra modules are needed. Include a sample JSON output comment after each serialise call.
What it does: Produces five copy-paste-ready snippets covering all common I/O variants for the exact class provided. Includes sample JSON output as inline comments so you can verify the mapping is correct without running the code first.
When to use it: When adding a new DTO to a Jackson 3 project and wanting verified, runnable code for every I/O operation before writing tests. Also useful when onboarding teammates who are new to Jackson’s API and need concrete examples rather than documentation links.
Configure REST Client Mapper
I am writing a typed REST client in Java using Jackson 3.1.2 that calls a third-party API. Configure a JsonMapper using the builder pattern with these requirements: unknown fields must not throw an exception, dates must serialise as ISO-8601 strings not epoch milliseconds, null fields must be excluded from outbound request bodies, and single-quoted JSON must be accepted if the target API is lenient. Add a one-line comment on every builder call explaining the exact runtime effect of that setting.
What it does: Generates a fully commented JsonMapper.builder() block tailored to REST client usage, with each setting explained in plain English immediately below it. The output is suitable for pasting directly into a @Configuration class or a client unit test fixture.
When to use it: When writing a client against an external API that may evolve its schema, returns ISO-8601 dates, and where you want clean, minimal outbound payloads. Especially valuable when the API documentation is incomplete and you need the mapper to be tolerant of unexpected fields without masking genuine deserialisation errors.
Deserialise Generic Collections
Using Jackson 3.1.2, show me how to deserialise these four JSON structures into typed Java collections: a JSON array into List<OrderDto>, a JSON object into Map<String, OrderDto>, a paginated wrapper like {“content”:[…],”totalElements”:100} into a generic Page<OrderDto> class, and an array of unknown objects into List<Map<String, Object>>. Explain why TypeReference is required for each case and what goes wrong if you pass List.class directly.
What it does: Provides four complete examples with working TypeReference instantiation patterns for each collection shape, explains Java type erasure and why List.class produces an untyped List<LinkedHashMap> instead of the expected typed list, and shows the generic page wrapper pattern common in Spring Data REST responses.
When to use it: When consuming paginated REST APIs, batch endpoints returning JSON arrays, or any response whose root element is a collection or generic wrapper. Run this prompt when readValue(json, List.class) compiles but produces ClassCastException at runtime when you try to use the list elements.
Conclusion
ObjectMapper is the foundation of all Jackson-based JSON handling in Java. Understanding how to create it correctly (once, thread-safe, properly configured), how to serialise and deserialise both simple objects and generic collections, and which configuration flags matter most will take you through the vast majority of real-world JSON tasks. The subsequent parts of this series build on this foundation to cover annotations, custom serialisers, polymorphism, streaming performance, and security.