22

I am developing using an ORM where I extend a base orm class to create tables.

For example:

public class Person extends DbItem {
    @JsonIgnore
    private String index;

    private String firstName;

    private String lastName;
}

Problem is that when I use ObjectMapper to serialize, it tries to serialize the members of the DbItem class. Is there any simple way to prevent this? For example with an annotation.

I had a look at a similar problem Jackson serialization: how to ignore superclass properties but I was hoping it could be done simpler, and I'm not sure if I could do it as I can't change the superclass since it is in an external library.

Community
  • 1
  • 1
Simen Russnes
  • 2,002
  • 2
  • 26
  • 56
  • Have you tried playing with `@JsonIgnoreProperties` at class level, combined with `@JsonProperty` for the `Person` props you need? Not sure it's applicable tbh, just a thought. – Mena Apr 14 '15 at 14:51

2 Answers2

22

You can use a Mix-in or @JsonIgnoreProperties

For the purposes of these examples, the base ORM class and extension are assumed to be:

public class DbItem {
    public String dbPropertyA;
    public String dbPropertyB;
}

and

public class Person extends DbItem {
    public String index;
    public String firstName;
    public String lastName;
}

respectively.

Using a Mix-in

A Mix-in is an abstraction of the de/serialization instructions that Jackson understands from an object itself. It is a way to customize de/serialization of 3rd party classes. In order to define a Mix-in, an abstract class must be created and registered with the ObjectMapper.

Example Mix-in Definition

public abstract class PersonMixIn {
    @JsonIgnore public String dbPropertyA;
    @JsonIgnore public String dbPropertyB;
    @JsonIgnore public String index;
}

Registering the Mix-in

@Test
public void serializePersonWithMixIn() throws JsonProcessingException {
    // set up test data including parent properties
    Person person = makeFakePerson();

    // register the mix in
    ObjectMapper om = new ObjectMapper()
            .addMixIn(Person.class, PersonMixIn.class);

    // translate object to JSON string using Jackson
    String json = om.writeValueAsString(person);

    assertFalse(json.contains("dbPropertyA"));
    assertFalse(json.contains("dbPropertyB"));
    assertFalse(json.contains("index"));
    System.out.println(json);
}

@JsonIgnoreProperties

If you want to avoid creating a class and configuring the ObjectMapper, the @JsonIgnoreProperties annotation can be utilized. Simply annotate the class you are serializing and list the properties to exclude.

Example Serializable Object

@JsonIgnoreProperties({"index", "dbPropertyA", "dbPropertyB"})
public class Person extends DbItem {
    public String index;
    public String firstName;
    public String lastName;
}

See It In Action

@Test
public void serializePersonWithIgnorePropertiesAnnotation() throws JsonProcessingException {
    // set up test data including parent properties
    Person person = makeFakePerson();

    ObjectMapper om = new ObjectMapper();

    // translate object to JSON string using Jackson
    String json = om.writeValueAsString(person);

    assertFalse(json.contains("dbPropertyA"));
    assertFalse(json.contains("dbPropertyB"));
    assertFalse(json.contains("index"));
    System.out.println(json);
}
Sam Berry
  • 7,394
  • 6
  • 40
  • 58
  • 1
    So I would have to include all members of the base class in the PersonMixIn then right? I was hoping for something simpler but I guess it's a way to go. Problem is that whenever the base class changes, it would require maintenance on the code – Simen Russnes Apr 15 '15 at 09:28
  • @simernes there is also a `@JsonIgnoreProperties` annotation that can be used on the child class. Same thing applies, you need to list all of the properties that you want to exclude. Since the base class is a 3rd party library, I would assume you're not updating the version of the lib in your project frequently? I'd recommend writing a unit test to confirm the desired serialization of the `Person` object so that you know when the base has changed and the Mix-in needs updating. – Sam Berry Apr 15 '15 at 11:45
  • I'll update the answer to include an example of both. – Sam Berry Apr 15 '15 at 12:41
  • 1
    This even works for overriding `@JsonIdentityInfo` annotations in super classes. Great find! – Roben Feb 01 '16 at 11:15
0

You want to do custom field level serialization. This will be a bit more work to maintain your code base, but is by far the simplest solution. See Jackson JSON custom serialization for certain fields for implementation details.

Community
  • 1
  • 1
Matthew Herbst
  • 29,477
  • 23
  • 85
  • 128