Jackson Data-Processing Tools

repository·main·Indexed 27 days ago

https://github.com/fasterxml/jackson

A comprehensive suite of data-processing tools for the JVM, specializing in high-performance JSON parsing, POJO data-binding, and support for formats including XML, YAML, Avro, CBOR, Protobuf, and Smile. The project consists of core modules (jackson-core, jackson-annotations, jackson-databind), specialized datatype modules, and a lightweight alternative called jackson-jr. It currently supports multiple major versions (1.x, 2.x, and 3.x) to allow incremental migration, with Jackson 3.x requiring Java 17.

Tokens
7.4K
Snippets
9
Records
49
Agent score
95%

What's inside Jackson

  1. Overview of Jackson Data-Processing Tools

    main

    Jackson is a suite of data-processing tools for Java and the JVM platform. It is primarily used for JSON processing but extends to many other formats and data types.

    Core Components:

    • Streaming API: High-performance streaming parser/generator.
    • Databind: Data-binding library for mapping POJOs to and from JSON.
    • Annotations: A set of annotations used to control serialization and deserialization behavior.

    Supported Data Formats: Jackson supports various formats via specialized modules, including:

    • Avro, BSON, CBOR, Protobuf, Smile
    • CSV, TOML, YAML, XML, (Java) Properties
  2. Major Changes in Jackson 3.x

    main

    The migration from Jackson 2.x to 3.x involves several fundamental changes:

    1. JDK Baseline: Raised to Java 17 (previously Java 8).
    2. New Maven Group-ID and Packages: Most artifacts move from com.fasterxml.jackson to tools.jackson.
      • Exception: jackson-annotations retains its 2.x group-id/package, but annotations within jackson-databind (like @JsonSerialize) move to tools.jackson.databind.annotation.
    3. Removal of Deprecated API: All methods, fields, and classes marked @Deprecated as of Jackson 2.20 are removed.
    4. Immutability: ObjectMapper and JsonFactory are now fully immutable. You must use the builder pattern to construct instances.
    5. Mandatory Format-Aligned Mappers: You can no longer use new ObjectMapper(new YAMLFactory()). You must use specific mappers like new YAMLMapper() or new XmlMapper().
    6. Unchecked Exceptions: All Jackson exceptions are now RuntimeExceptions. The base exception JsonProcessingException is renamed to JacksonException and no longer extends IOException.
    7. Built-in Java 8 Modules: The following modules are now built into jackson-databind and do not require separate registration:
      • jackson-module-parameter-names (constructor parameter name auto-detection)
      • jackson-datatype-jdk8 (java.util.Optional support)
      • jackson-datatype-jsr310 (java.time support)
  3. Core Jackson modules overview

    main

    Jackson's functionality is built upon three core modules:

    • jackson-core: Provides the low-level streaming API and includes JSON-specific implementations.
    • jackson-annotations: Contains the standard Jackson annotations used for configuring serialization and deserialization.
    • jackson-databind: Implements data-binding and object serialization support. It builds upon jackson-core and jackson-annotations.
  4. Use Jackson jr for lightweight requirements

    main

    If the full jackson-databind library has too much footprint or startup overhead (e.g., for mobile devices or simple tasks), use jackson-jr.

    jackson-jr is a smaller, more compact library that builds on the jackson-core Streaming API but does not depend on databind. It provides a simplified subset of Jackson's functionality.

  5. Choose a Jackson Processing Model

    main

    Jackson provides four primary ways to process JSON data depending on your performance and complexity requirements:

    1. Tree Model (JsonNode): Best for navigating and manipulating JSON structures without mapping to specific Java classes. Supports JsonPointer for locating specific nodes.
    2. POJOs (Data-binding / Mapping): The most common approach. Maps JSON directly to Java objects (Plain Old Java Objects) using ObjectMapper.
    3. Streaming API: The lowest-level, highest-performance model. Uses JsonParser and JsonGenerator to process tokens one by one. Ideal for very large datasets where memory footprint must be minimized.
    4. 'Untyped' Java objects: Converts JSON into standard Java collections like List and Map.
  6. Extend Jackson with Modules and Data Formats

    main

    Jackson is highly extensible through several mechanisms:

    • Datatype Modules: Add support for new data types (e.g., JSR-310 dates).
    • Dataformat Extensions: Support formats other than JSON (e.g., XML, Avro).
    • JVM Language Support: Specialized modules for Scala and Kotlin.
    • Other Extensions: Includes Afterburner (for performance), Mr. Bean, and support for JAXB Annotations.
  7. Choose the correct Jackson major version

    main

    Jackson is available in three major versions. Choose based on your project requirements:

    • 3.x (tools.jackson): The newest actively developed version. It includes new functionality and is recommended for new projects.
    • 2.x (com.fasterxml.jackson): The previous major version. It is still actively maintained and widely adopted.
    • 1.x (org.codehaus.jackson): Deprecated. New use is strongly discouraged. Sources are available in the jackson-1 repository.

    Note that changes are rolled forward from 2.x to 3.x, but not in reverse. Major versions use different Java packages and Maven groupIds, allowing different major versions to coexist on the same classpath for incremental migration.

  8. Order import statements in Jackson projects

    main

    Group and order imports in the following sequence:

    1. JDK Imports: Standard Java imports.
    2. General 3rd Party Imports: Libraries like JUnit.
    3. Jackson Core Types: Ordered by annotation, then core, then databind.
    4. Component-Specific Types: Specific Jackson component types.

    Static imports should follow the same ordering logic and be grouped after non-static imports.

    import java.io.*;           // JDK imports
    import java.util.*;
    
    import org.junit.*;         // General 3rd party imports
    
    import com.fasterxml.jackson.annotation.*;  // Jackson core types: annotations
    
    import com.fasterxml.jackson.core.*;        // Jackson core types: core
    import com.fasterxml.jackson.databind.*;    // Jackson core types: databind
    
    import com.fasterxml.jackson.other.modules.*; // Component-specific imports
    
    // static imports follow the same pattern
  9. Name test classes and manage failing tests

    main

    Test Class Naming

    Use the suffix Test for class names (e.g., XxxTest). This ensures compatibility with JUnit and Maven, which requires test classes to either start or end with Test to be included in runs.

    Handling Failing Tests

    For bug reproduction, place failing tests in a dedicated directory: src/test/java/**/failing. These tests are excluded from automatic execution and are intended for manual runs to investigate reported issues.

  10. Implement Custom Handlers for Serialization and Deserialization

    main

    You can extend Jackson's behavior by implementing custom logic:

    Databinding Customization:

    • PropertyNamingStrategy: Change how Java field names map to JSON keys.
    • Mix-Ins: Add annotations to classes you do not own.
    • InjectableValues: Inject values during deserialization.
    • JsonInclude: Control which properties are included in the output.
    • DateFormat & TimeZone: Configure date/time handling.
    • Visibility: Control which fields (private/public) are accessible.

    Custom Deserialization:

    • Custom deserializers
    • Value instantiators
    • Value injections

    Custom Serialization:

    • Custom serializers
    • Value instantiators
    • Filtering

    Streaming Customization:

    • CharacterEscapes for custom character handling.
    • PrettyPrinter for output formatting.
  11. Configure immutable ObjectMapper using Builders

    main

    In Jackson 3, ObjectMapper and JsonFactory are fully immutable. You can no longer use setter methods for configuration. Instead, use the builder() pattern.

    General Configuration

    final JsonMapper mapper = JsonMapper.builder()
       .addModule(new JodaModule())
       .enable(JsonWriteFeature.ESCAPE_NON_ASCII)
       .build();

    Reconfiguring an existing instance

    To create a new instance based on an existing one, use .rebuild():

    JsonMapper mapper2 = mapper.rebuild()
       .enable(SerializationFeature.INDENT_OUTPUT)
       .build();

    Date Format and Time Zone

    ObjectMapper mapper = JsonMapper.builder()
      .defaultDateFormat(new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"))
      .defaultTimeZone(TimeZone.getDefault())
      .build();

    Serialization Inclusion

    ObjectMapper mapper = JsonMapper.builder()
      .changeDefaultPropertyInclusion(incl -> incl.withValueInclusion(JsonInclude.Include.NON_NULL))
      .changeDefaultPropertyInclusion(incl -> incl.withContentInclusion(JsonInclude.Include.NON_NULL))
      .build();

    Visibility

    ObjectMapper mapper = JsonMapper.builder()
        .changeDefaultVisibility(vc ->
            vc.withFieldVisibility(JsonAutoDetect.Visibility.NONE))
        .build();

    Default Serialization/Deserialization Views (Jackson 3.1+)

    ObjectMapper mapper = JsonMapper.builder()
        .defaultSerializationView(Views.Public.class)
        .defaultDeserializationView(Views.Public.class)
        .build();
    final JsonMapper mapper = JsonMapper.builder() // format-specific builders
       .addModule(new JodaModule()) // to use Joda date/time types
       .enable(JsonWriteFeature.ESCAPE_NON_ASCII) // configure streaming JSON-escaping
       .build();
  12. Migrate Gradle dependencies to Jackson 3

    main

    When migrating to Jackson 3, update your Gradle build files to use the new tools.jackson group ID. Use the jackson-bom platform to enforce compatible versions and declare modules without explicit versions.

    plugins {
        id 'java'
    }
    repositories {
        mavenCentral()
    }
    dependencies {
        implementation platform("tools.jackson:jackson-bom:3.0.0")
        // Now declare Jackson modules WITHOUT versions
        implementation "tools.jackson.core:jackson-databind"
    }