Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jackson2 PropertyFilter for nested properties, or is there another way?

I'm currently searching a way to serialize an object in multiple ways without interfering with the classes directly. (like adding lots of annotations)

Imagine a class like this:

class User {
  String id;
  String name;
  String email;
  ...
  User manager;
}

The SimplePropertyFilter delivers almost the desired functionality but the problem is that this filter ignores the level of the current object and applies all defined filters on each object, whether it is a nested one or not.

I'm not limited to Filters, but I would like to avoid writing multiple classes for each of the desired json response. Is there a way to achieve this behavior with Jackson2 ?


If we would like to serialize this for an edit form we need all fields, but for a list of users we probably just need some of them.

For the manager however we always would need "only" the id and the name. And this is what search a solution for.

The JSON output should become something like this:

{
  "id" : "20",
  "login" : "USER20",
  "name" : "User 20",
  "email" : "[email protected]",
  "manager" : {
     "id" : "1",
     "name" : "Administrator"
  }
}

I feel like the property filter approach is getting me quite close to the desired solution but from what i found out you can only define "simple" properties.

public class UserJsonWriter {
  public String toJson() {
    SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("id", "login", "name", "email", "manager");
    // Unfortunatly I cannot write:
    SimpleBeanPropertyFilter filter = SimpleBeanPropertyFilter.filterOutAllExcept("id", "login", "name", "email", "manager.id", "manager.name");


    User user = userService.getUser(20);
    ObjectMapper copy = objectMapperFactoryBean.getCopy();
    copy.addMixInAnnotations(User.class, CustomFilter.class);
    ObjectWriter writer = copy.writer(new SimpleFilterProvider().addFilter("customFilter", filter));
    return writer.writeValueAsString(user);
  }
}

@JsonFilter("customFilter")
public class CustomFilter {

}

And currently the output looks like this.

{
  "id" : "20",
  "login" : "USER20",
  "name" : "User 20",
  "email" : "[email protected]",
  "manager" : {
     "id" : "1",
     "login" : "ADMIN",
     "name" : "Administrator",
     "email" : "[email protected]",
     "manager" : {
       ... (might continue multiple times)
     }
   }
}

From what I can tell, the PropertyFilter does not know the current "location" of the serialization, neither does the json generator (directly).

The simplest solution that i can see to be used would look for nested properties during this filtering process. Does this possibility exist in Jackson? Probably there are other libraries that support this behaviour?

EDIT: I also like to add that I'm using Spring MVC, probably there is a way through Spring?

Thanks

like image 881
Martin Frey Avatar asked Oct 19 '22 23:10

Martin Frey


1 Answers

Answering my own question with YES and a little addon library on github.

https://github.com/Antibrumm/jackson-antpathfilter

like image 111
Martin Frey Avatar answered Oct 22 '22 12:10

Martin Frey