Master Jackson in Spring Boot: Essential Annotations and Extension Points

This article provides a comprehensive guide to Jackson’s most frequently used annotations, core modules, and extension points in Spring Boot, illustrating each feature with concrete Java code examples that show how to customize serialization, deserialization, property handling, and polymorphic type processing.

Programmer1970
Programmer1970
Programmer1970
Master Jackson in Spring Boot: Essential Annotations and Extension Points

1. Common Jackson Annotations

@JsonSerialize / @JsonDeserialize

@JsonProperty

@JsonIgnore

@JsonFormat

@JsonUnwrapped

@JsonAnyGetter

@JsonInclude

@JsonAlias

@JsonIgnoreProperties

@JsonManagedReference / @JsonBackReference

@JsonCreator

@JsonTypeInfo

@JsonFilter

@JsonAnySetter

@JsonAppend

@JsonIgnoreType

@JsonGetter / @JsonSetter

@JsonPropertyOrder

@JsonSerialize and @JsonDeserialize

These annotations let you plug in custom serializer and deserializer classes to control how an object is converted to and from JSON.

import com.fasterxml.jackson.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
public class Person {
    private String name;
    private int age;
    // constructors, getters, setters omitted

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person("John", 30);
        String json = mapper.writeValueAsString(person);
        System.out.println(json); // {"fullName":"John","years":30}
        Person deserialized = mapper.readValue(json, Person.class);
        System.out.println(deserialized); // Person{name='John', age=30}
    }
}

class CustomSerializer extends JsonSerializer<Person> {
    @Override
    public void serialize(Person person, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("fullName", person.getName());
        gen.writeNumberField("years", person.getAge());
        gen.writeEndObject();
    }
}

class CustomDeserializer extends JsonDeserializer<Person> {
    @Override
    public Person deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode node = p.getCodec().readTree(p);
        String fullName = node.get("fullName").asText();
        int years = node.get("years").asInt();
        return new Person(fullName, years);
    }
}

@JsonProperty

Specifies the JSON field name used during serialization and deserialization.

public class MyClass {
    @JsonProperty("customName")
    private String property;
    // getters and setters omitted
}

@JsonIgnore

Marks a property to be ignored by both serialization and deserialization.

public class MyClass {
    @JsonIgnore
    private String secret;
    // getters and setters omitted
}

@JsonFormat

Controls formatting of dates, times, or other special types.

public class Event {
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date eventDate;
}

public class Payment {
    @JsonFormat(shape = JsonFormat.Shape.STRING,
                pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ",
                timezone = "GMT+8")
    private LocalDateTime paymentTime;
}

@JsonUnwrapped

Flattens a nested object’s properties into the outer JSON object. Optional prefix and suffix can be used to add a prefix or suffix to the flattened fields.

public class Employee {
    private String name;
    @JsonUnwrapped
    private Address address;
}

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

// Serializing an Employee instance yields:
// {"name":"John Doe","city":"New York","street":"123 Main St"}

@JsonAnyGetter

Exposes a Map<String, Object> as additional JSON properties, allowing dynamic key‑value pairs.

public class MyClass {
    private Map<String, Object> properties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getProperties() { return properties; }

    public void addProperty(String key, Object value) { properties.put(key, value); }
}

@JsonInclude

Controls inclusion of null or empty values. Example uses Include.NON_NULL to omit null fields.

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
    private String name;
    private Integer age; // may be null
    private String address; // may be null
}

// Serializing a Person with null age and address produces: {"name":"John"}

@JsonAlias

Defines alternative names for a property during deserialization.

public class MyClass {
    @JsonAlias({"name", "fullName"})
    private String property;
}

@JsonIgnoreProperties

Ignores a set of properties globally for a class.

@JsonIgnoreProperties({"property1", "property2"})
public class MyClass {
    private String property1;
    private String property2;
    private String property3;
}

@JsonManagedReference and @JsonBackReference

Breaks circular references by designating the forward and back sides of a parent‑child relationship.

public class Parent {
    private String name;
    @JsonManagedReference
    private List<Child> children;
}

public class Child {
    private String name;
    @JsonBackReference
    private Parent parent;
}

@JsonCreator

Marks a constructor or static factory method to be used for deserialization, often combined with @JsonProperty to bind JSON fields.

public class MyClass {
    private String property;

    @JsonCreator
    public MyClass(@JsonProperty("property") String property) {
        this.property = property;
    }
}

@JsonTypeInfo (with @JsonSubTypes)

Enables polymorphic type handling by adding type metadata to JSON.

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal { /* common fields */ }

public class Dog extends Animal { /* dog specific */ }
public class Cat extends Animal { /* cat specific */ }

@JsonFilter

Allows dynamic inclusion/exclusion of properties at runtime.

@JsonFilter("myFilter")
public class MyDto {
    private String name;
    private int age;
    private String email;
}

ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider fp = new SimpleFilterProvider();
fp.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name", "age"));
mapper.setFilterProvider(fp);
String json = mapper.writer(fp).writeValueAsString(new MyDto()); // only name and age appear

@JsonAnySetter

Collects unknown JSON fields into a map, enabling flexible deserialization of extra data.

public class MyClass {
    private Map<String, Object> additionalProperties = new HashMap<>();

    @JsonAnySetter
    public void setAdditionalProperty(String key, Object value) {
        additionalProperties.put(key, value);
    }
}

@JsonAppend

Appends virtual properties to the JSON output, either via static attributes or by implementing a custom VirtualBeanPropertyWriter.

@JsonAppend(attrs = {@JsonAppend.Attr(value = "age"), @JsonAppend.Attr(value = "height")},
            props = {@JsonAppend.Prop(value = TestWriter.class, type = String.class, name = "version")})
public class JsonPropertyPojo {
    private String sex;
    private String name;
    private String unknown;
}

// Example serialization adds "age", "height", and a computed "version" field.

@JsonIgnoreType

Completely excludes a type from serialization and deserialization.

@JsonIgnoreType
public class AdditionalInfo {
    private String info;
}

public class MyEntity {
    private String name;
    private AdditionalInfo additionalInfo;
}

// Serializing MyEntity yields {"name":"John"} – the AdditionalInfo field is omitted.

@JsonGetter and @JsonSetter

Define custom getter and setter method names for JSON properties.

public class Person {
    private String firstName;
    private String lastName;

    @JsonGetter("full_name")
    public String getFullName() { return firstName + " " + lastName; }

    @JsonSetter("first_name")
    public void setFirstName(String firstName) { this.firstName = firstName; }

    @JsonSetter("last_name")
    public void setLastName(String lastName) { this.lastName = lastName; }
}

@JsonPropertyOrder

Specifies the order of properties in the generated JSON string.

@JsonPropertyOrder({"id", "name", "email"})
public class User { /* fields */ }

2. Jackson Core Modules

databind : Core serialization/deserialization engine.

annotations : Provides the annotation set used throughout Jackson.

coreutils : Utility classes for type conversion, tree model handling, and byte‑array operations.

datatype‑jsr310 : Adds support for Java 8 date‑time types (e.g., LocalDateTime).

jaxrs‑json‑provider : Implements JAX‑RS JSON message conversion for REST services.

3. Jackson Extension Points

JsonSerializer / JsonDeserializer : Custom (de)serialization logic for specific types.

StdConverter : Generic type conversion, useful for annotation processing.

JsonNodeFactory : Custom factory for creating JsonNode instances.

JsonSerializerModifier / JsonDeserializerModifier : Hook to replace or modify default (de)serializers.

ValueInstantiator : Custom object creation strategy (e.g., factory methods).

ObjectIdResolver : Maps objects to identifiers, handling circular references.

ObjectIdentityGenerator : Generates unique identifiers for objects during serialization.

By combining these annotations, modules, and extension points, developers can fully control how Java objects are represented as JSON in Spring Boot applications, enabling features such as field masking, custom naming, polymorphic handling, and dynamic property injection.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaSerializationJSONSpring BootAnnotationsJacksonDeserialization
Programmer1970
Written by

Programmer1970

Formerly called 'Code to 35'. Add our main WeChat ID to access a wealth of shared resources (algorithms, interview prep, tech stacks: Java, Python, Go, big data). We mainly share serious development techniques, focusing on output-driven input. Occasionally we post life snippets and gossip. Our aim is to attract precise traffic and test advertising opportunities.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.