DEV Community

araf
araf

Posted on • Edited on

4 1 1 1 1

Mastering Jackson Annotations in Java with Real-World Examples

When working with Java and JSON, Jackson is often the go-to library. It provides a powerful and flexible way to convert Java objects to JSON and vice versa. But what really makes Jackson shine are its annotations, which allow fine-grained control over serialization and deserialization.

In this post, we’ll explore the most useful Jackson annotations with real-world examples to help you master JSON mapping in Java.


🔧 Setup

Add Jackson to your pom.xml:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.15.0</version>
</dependency>
Enter fullscreen mode Exit fullscreen mode

1. @JsonProperty: Rename Fields

public class User {
    @JsonProperty("full_name")
    private String name;
}
Enter fullscreen mode Exit fullscreen mode

Used to map JSON property names to Java fields when they don't match.


2. @JsonIgnore: Exclude Fields

public class User {
    private String name;

    @JsonIgnore
    private String password;
}
Enter fullscreen mode Exit fullscreen mode

Prevents sensitive data from being serialized.


3. @JsonInclude: Conditional Serialization

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Product {
    private String name;
    private String description;
}
Enter fullscreen mode Exit fullscreen mode

Avoids sending nulls in JSON payload.


4. @JsonFormat: Format Dates or Numbers

public class Event {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm")
    private LocalDateTime dateTime;
}
Enter fullscreen mode Exit fullscreen mode

Perfect for readable date/time serialization.


5. @JsonIgnoreProperties: Ignore Unmapped JSON Fields

@JsonIgnoreProperties(ignoreUnknown = true)
public class Customer {
    private String id;
    private String name;
}
Enter fullscreen mode Exit fullscreen mode

Avoids errors from unexpected JSON fields.


6. @JsonCreator + @JsonProperty: Constructor-Based Deserialization

public class Account {
    private final String id;
    private final String type;

    @JsonCreator
    public Account(@JsonProperty("id") String id, @JsonProperty("type") String type) {
        this.id = id;
        this.type = type;
    }
}
Enter fullscreen mode Exit fullscreen mode

Used when there's no default constructor.


7. @JsonValue: Custom Enum Serialization

public enum Status {
    ACTIVE("active"),
    INACTIVE("inactive");

    private final String value;

    Status(String value) {
        this.value = value;
    }

    @JsonValue
    public String getValue() {
        return value;
    }
}
Enter fullscreen mode Exit fullscreen mode

Control how enums are represented.


8. @JsonAlias: Support Multiple JSON Field Names

public class UserDTO {
    @JsonAlias({"fullName", "user_name"})
    private String name;
}
Enter fullscreen mode Exit fullscreen mode

Makes deserialization more flexible.


9. @JsonAnySetter: Dynamic JSON Properties to Map

public class Config {
    private Map<String, String> settings = new HashMap<>();

    @JsonAnySetter
    public void addSetting(String key, String value) {
        settings.put(key, value);
    }
}
Enter fullscreen mode Exit fullscreen mode

Great for handling dynamic key-value pairs.


10. @JsonAnyGetter: Dynamic Map to JSON

public class Config {
    private Map<String, String> settings;

    @JsonAnyGetter
    public Map<String, String> getSettings() {
        return settings;
    }
}
Enter fullscreen mode Exit fullscreen mode

Outputs dynamic fields from a map.


11. @JsonUnwrapped: Flatten Nested Object

public class Address {
    private String city;
    private String zip;
}

public class Person {
    private String name;

    @JsonUnwrapped
    private Address address;
}
Enter fullscreen mode Exit fullscreen mode

Useful when you don’t want a nested structure in the output.


12. @JsonDeserialize / @JsonSerialize: Custom (De)Serializers

public class Item {
    @JsonSerialize(using = CustomDateSerializer.class)
    private Date created;
}
Enter fullscreen mode Exit fullscreen mode

Full control over how specific fields are (de)serialized.


13. @JsonRootName: Wrap with Root Object

Jackson can wrap JSON inside a root name using @JsonRootName. This is useful in SOAP-like or legacy APIs.

@JsonRootName(value = "user")
public class User {
    private String id;
    private String name;
}
Enter fullscreen mode Exit fullscreen mode

Enable root wrapping:

ObjectMapper mapper = new ObjectMapper();
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);

User user = new User();
user.setId("1");
user.setName("Alice");

String json = mapper.writeValueAsString(user);
Enter fullscreen mode Exit fullscreen mode

Output:

{
  "user": {
    "id": "1",
    "name": "Alice"
  }
}
Enter fullscreen mode Exit fullscreen mode

To enable deserialization:

mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
Enter fullscreen mode Exit fullscreen mode

💡 Final Thoughts

Jackson’s annotation model is rich and adaptable to almost any real-world JSON structure you’ll face. Whether you’re building REST APIs, processing external JSON feeds, or persisting data, mastering these annotations will make your job much easier.

Have questions or a tricky mapping scenario? Drop it in the comments! 👇

Heroku

Amplify your impact where it matters most — building exceptional apps.

Leave the infrastructure headaches to us, while you focus on pushing boundaries, realizing your vision, and making a lasting impression on your users.

Get Started

Top comments (1)

Collapse
 
haraf profile image
araf

Dynatrace image

Observability should elevate – not hinder – the developer experience.

Is your troubleshooting toolset diminishing code output? With Dynatrace, developers stay in flow while debugging – reducing downtime and getting back to building faster.

Explore Observability for Developers