Problem: If there is a class say Person
class Person {
string name;
int age;
Address address;
.. getters and setters
}
How do we dynamically filter specific nested properties: name, address.state, address.zipcode reusing the same object mapper/writer.
One way is to follow the Spring integration to use property filter https://jira.spring.io/browse/SPR-12586. However, nested property filters are not supported. This is because of the way Jackson integration works. This is a very common use case to get only the fields clients are interested in runtime.
There are a few implementations already available that are slow because they lookup the jgen root context to build the nested path every time a property is checked if it can be filtered. These implementations also won't work without explicitly adding JsonFilter annotation on all classes that will be filtered:
https://github.com/PressAssociation/partial-response/tree/master/filter-json-jackson
https://github.com/Antibrumm/jackson-antpathfilter
https://github.com/narusas/SpringMvcJacksonFilter
The following won't work without @JsonFilter("antPathFilter") on all classes
objectMapper.addMixIn(Object.class, AntPathFilterMixin.class);
filter = new SimpleFilterProvider()
.addFilter("antPathFilter",
new AntPathPropertyFilter("nestedObj", "nestedObj.nestedProperty")
jacksonValue.setFilters(filter);
One work around is to explicitly set the same @JsonFilter("antPathFilter") on all classes that are nested, which did not make any sense to me. What if I wanted to support multiple filters at the same time tomorrow?
I also ended up writing my own implementation that is fast and that uses SimplePropertyFilter per class built on the nested properties.
The problem really is the way Jackson APIs requests a filter for current property without any context on the current class owning that property.
Always open for PRs if someone else has an itch.
My library https://github.com/krishna81m/jackson-nested-prop-filter is a work around that still works fast but the underlying Jackson library needs a modification.
Can I make a code recommendation by requesting a pull?
@krishna81m Sure, I can consider additions/improvements to API so please send an PR.
@krishna81m Are you working on that PR you mention? I think it's a nice feature i would love to have in jackson
@fgaule , for now, this work around https://github.com/krishna81m/jackson-nested-prop-filter (working draft) was enough for us to start using dynamic nested property filters. I have a few ideas for supporting this directly in Jackson but never had chance to spend time. Will start looking into it sometime in April.
Jersey's Entity Filtering has a Jackson FilterProvider which does nested property filtering; see [1].
For what I can understand it uses a generalized Jersey's SPI to build a sort of _entity graph_ and then uses it to build the Jackson filters. I guess the same logic could be extracted and adapted to provide the same feature in Jackson's databind, maybe with a specialized Visitor (I'm thinking for example about the JsonFormatVisitorWrapper used for JSON Schema).
[1] [https://github.com/jersey/…/jackson/internal/JacksonObjectProvider.java](https://github.com/jersey/jersey/blob/master/media/json-jackson/src/main/java/org/glassfish/jersey/jackson/internal/JacksonObjectProvider.java)
Hmm, was not aware of this but I did the something similar in my work around, build the entity graph first (ugly version containing just class or attribute) and then apply the filter based on the type of entity being filtered.
@krishna81m has done a little different, he navigate the whole object to be written to collect a property graph, adding an extra navigation when serializing (that navigation only occurs once cause of caching, isn't it?)
@herau I have been checking the visitor you mention (it's not a visitor as i expected), i couldn't find if it navigates the object graph as we need to adapt Jersey solution.
I think it needs a whole refactor of the filtering feature, cause in case we implement nested properties, all the stuff is coded written right now to support root level property filtering would be obsolete.
I have intention to make the effort to contribute with this feature, but i would like to have a clear picture of what we have/can do
@fgaule , it was the original idea, cache the navigation graph per root object filter just once, and then lookups from HashMaps are fast.
Agreed, we need to refactor quite a bit as this is just a workaround.
I don't think I know what should be done here; but I do note that some new functionality has been added in JsonParser; specifically, in Jackson 2.5, ability to set and get "current value" which is the POJO being read. This combined with parent stack of current property names should allow building nested filters. But I don't see things to work on in Jackson proper itself at this point.
For new specific ideas, requests, feel free to file a new issue.
I wrote a library called Squiggly Filter, which selects fields based on a subset of the Facebook Graph API syntax. For example, to select the zipCode of the address field of the user object, you would use a filter address{zipCode}.
More information here
Most helpful comment
I wrote a library called Squiggly Filter, which selects fields based on a subset of the Facebook Graph API syntax. For example, to select the zipCode of the address field of the user object, you would use a filter
address{zipCode}.More information here