Introduction
Jackson is the default JSON library for the Java ecosystem, used by Spring Boot, Quarkus, and most major frameworks. It provides three processing models: streaming (low-level token-based), tree model (in-memory JsonNode), and data binding (automatic POJO-to-JSON mapping), covering everything from simple serialization to complex schema-driven transformations.
What Jackson Does
- Serializes Java objects (POJOs, records, collections) to JSON strings or byte streams
- Deserializes JSON input into typed Java objects with automatic type detection
- Provides a tree model (JsonNode) for navigating and manipulating JSON without predefined classes
- Supports additional data formats through extension modules: XML, YAML, CSV, CBOR, MessagePack, Protobuf
- Handles polymorphic types, custom serializers/deserializers, and mix-in annotations for third-party classes
Architecture Overview
Jackson is organized into three core modules: jackson-core provides the streaming API (JsonParser and JsonGenerator) for token-level reading and writing; jackson-annotations defines the annotation types (@JsonProperty, @JsonIgnore, etc.); and jackson-databind builds the ObjectMapper on top of the streaming layer, implementing reflection-based data binding and the tree model. Extension modules plug into this architecture to add format support (jackson-dataformat-xml), data type handling (jackson-datatype-jsr310 for Java 8 dates), or framework integration (jackson-module-kotlin).
Self-Hosting & Configuration
- Add jackson-databind as a Maven or Gradle dependency; it transitively pulls in jackson-core and jackson-annotations
- Create a single ObjectMapper instance and reuse it across the application (it is thread-safe after configuration)
- Configure serialization features like indentation, null handling, and date format via mapper.configure() or mapper.setSerializationInclusion()
- Register modules for Java 8 date/time (JavaTimeModule), Kotlin data classes (KotlinModule), or other data formats
- Use @JsonProperty, @JsonIgnore, @JsonCreator, and @JsonFormat annotations on POJOs to control mapping behavior
Key Features
- Three processing models (streaming, tree, data binding) in one library for different performance and convenience needs
- Extensive annotation support for fine-grained control over serialization and deserialization
- Module system for extending format support (XML, YAML, CSV, CBOR) without changing application code
- High performance through streaming internals, with optional afterburner/blackbird modules for bytecode-level optimization
- Default JSON library in Spring Boot, Quarkus, Dropwizard, and most Java web frameworks
Comparison with Similar Tools
- Gson — Google's JSON library; simpler API but slower and less feature-rich than Jackson for complex use cases
- JSON-B (Yasson) — Jakarta EE standard JSON binding; portable across implementations but smaller ecosystem than Jackson
- Moshi — Square's JSON library for Android/Kotlin; lighter weight with Kotlin-first design
- org.json — minimal reference implementation; useful for simple tasks but lacks data binding and performance optimizations
- FastJSON — Alibaba's JSON library; fast but has had security vulnerabilities and non-standard behavior
FAQ
Q: Is ObjectMapper thread-safe? A: Yes, once fully configured. Do not modify an ObjectMapper after it is shared across threads. Create a single instance at startup and reuse it, or use ObjectMapper.copy() for variant configurations.
Q: How do I handle Java 8 date/time types like LocalDate and Instant? A: Register the JavaTimeModule: mapper.registerModule(new JavaTimeModule()). Without it, Java 8 date types serialize as nested objects instead of ISO strings.
Q: Can Jackson process formats other than JSON? A: Yes. Jackson has dataformat modules for XML (jackson-dataformat-xml), YAML, CSV, CBOR, Smile, MessagePack, Ion, and Protobuf. The ObjectMapper API stays the same; only the underlying parser/generator changes.
Q: How do I ignore unknown JSON fields during deserialization? A: Configure the mapper with mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false), or annotate the class with @JsonIgnoreProperties(ignoreUnknown = true).