1. Overview

In this tutorial, we’ll investigate how we can serialize properties with different access modifiers. Additionally, we’ll look at the usage of accessor methods during serialization.

2. Serializing Package-private fields

Let’s start with package-private fields.

By default, Jackson can’t serialize package-private fields. This is because Jackson needs public accessor methods for getting field values:

public class DefaultPerson {

    String name;
    int age;

    public DefaultPerson() {
    }

    public DefaultPerson(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

Here, DefaultPerson class has two package-private fields with no public accessors.

Similar to private field serialization, serialization of package-private fields results in an exception:

@Test(expected = JsonProcessingException.class)
public void shouldNotSerialize_WithDefaultFields() throws JsonProcessingException {
    DefaultPerson defaultPerson = new DefaultPerson("john", 21);

    objectMapper.writeValueAsString(defaultPerson);
}

This is the case when we use Jackson with its default settings. However, we canĀ change the visibility settings of Jackson to serialize package-private fields.

3. Serialize Public Fields using Jackson

Now, let’s look at public field serialization.

Unlike package-private fields, Jackson can serialize public fields even if they don’t have public accessors.

We have the PublicPerson class:

public class PublicPerson {

    public String name;
    public int age;

    public PublicPerson() {
    }

    public PublicPerson(String name, int age) {
        this.name = name;
        this.age = age;
    }
}

When we serialize an instance of PublicPerson, it successfully runs:

@Test
public void shouldSerialize_WithPublicFields() throws JsonProcessingException {
    PublicPerson publicPerson = new PublicPerson("john", 21);

    String json = objectMapper.writeValueAsString(publicPerson);

    assertThat(json).isEqualTo("{\"name\":\"john\",\"age\":21}");
}

4. Serialize with Getter Methods

Jackson can also serialize with getter methods even if the fields are private:

public class GetterPerson {

    private String name;
    private int age;

    public GetterPerson() {
    }

    public GetterPerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }
}

Here we have GetterPerson with two fields and corresponding getter methods.

When Jackson serializes an instance, it extracts the JSON field names from the JavaBean style methods:

@Test
public void shouldSerialize_WithGetters() throws JsonProcessingException {
    GetterPerson getterPerson = new GetterPerson("john", 21);

    String json = objectMapper.writeValueAsString(getterPerson);

    assertThat(json).isEqualTo("{\"name\":\"john\",\"age\":21}");
}

Here, name is extracted from getName() and age is extracted from getAge() method.

5. Serialize Custom JavaBean Style Methods

In a class, there can be methods that don’t have a field directly backing it. However, if this method conforms to JavaBean rules, Jackson uses it in serialization:

public class CustomGetterPerson {

    private String name;
    private int age;

    public CustomGetterPerson() {
    }

    public CustomGetterPerson(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public int getAge() {
        return 999;
    }

    public String getName() {
        return name;
    }

    public int getPreviousAge() {
        return age - 1;
    }

    public int nextAge() {
        return age + 1;
    }
}

Here, theĀ getPreviousAge() method doesn’t have a backing field, previousAge.

When Jackson serializes the instance, resulting JSON also includes a field named as previousAge. Note that serialized class doesn’t have a field with that name, but has a method. Also note that, since nextAge() method isn’t a valid JavaBean method, it isn’t included in resulting JSON:

@Test
public void shouldSerialize_WithCustomGetter_AndAdditionalMethods() throws JsonProcessingException {
    CustomGetterPerson customGetterPerson = new CustomGetterPerson("john", 21);

    String json = objectMapper.writeValueAsString(customGetterPerson);

    assertThat(json).isEqualTo("{\"name\":\"john\",\"age\":999,\"previousAge\":20}");
}

6. Summary

In this tutorial, we’ve investigated serializing properties with different access modifiers. Additionally, we’ve investigated the usage of methods during serialization.

As always, the source code is available on Github.

Leave a Reply

Close Menu