Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow specifying custom exclusion comparator via @JsonInclude, using JsonInclude.Include.CUSTOM #888

Closed
cowtowncoder opened this issue Aug 6, 2015 · 7 comments
Milestone

Comments

@cowtowncoder
Copy link
Member

(note, possible related to #885. Also note that this supercedes #558)

Choices used with @JsonInclude are currently somewhat limited, and specifically require either hard-coded criteria (null, or default property values of a POJO) or support from JsonSerializer for type (for "empty" check via `JsonSerializer.isEmpty(...)).
This makes it difficult to have custom criteria for exclusion without using other mechanisms like JSON Views or Json filter.

But it would seem possible to instead allow use of some kind of custom object that is called to determine whether given value is to be included/excluded.
While there are multiple possible ways to go about with this -- specifically, whether to create a new interface for comparing -- but one very simple way would be to simply use Object.equals(); method of comparator, and use return value to indicate inclusion (if true returned) vs exclusion (false).

The only other thing needed would seem to be to modify @JsonInclude so that:

  1. There is a way specify the Class of custom comparator (default of Void.class to indicate "no custom comparator")
  2. (optional) Add yet another JsonInclude.Include enum choice of CUSTOM
  3. Also probably need to implement Jackson 2.7: use AnnotationIntrospector.findPropertyInclusion() #839

Of these, (2) is optional: we could choose to always check custom comparator, and if one defined, ignore enum. But from readability stand-point it seems better to add a new choice.

Also: for maximum power, we could choose to instead require implementation of some special interface, through which we could pass context (SerializerProvider). While this would be powerful, it seems that perhaps it is better not get carried away at this point: given that there are more powerful mechanisms for doing that (JSON Filter), we may want to keep this feature simple.

@kdkeck
Copy link

kdkeck commented Aug 14, 2015

I've been grappling with the same problem, but my preferred solution would be slightly different, perhaps because my use case is different. My use case is that there's one specific object type I'd like to define a custom isEmpty() definition for, and I'd prefer to be able to just annotate a boolean isEmpty() method in that class with an annotation (something like JsonIsEmptyPredicate) rather than have to implement a custom serializer or SerializerModifier.

@cowtowncoder
Copy link
Member Author

@kdkeck Interesting idea, although from performance perspective that would be quite inefficient unfortunately, since the call to the method would have to be via Reflection. Possibly not a big deal for many users. Would need quite a bit of support for introspection (via AnnotationIntrospection), but otherwise seems doable.

I will keep the idea in mind as an alternative; it has some benefits. And the more general idea of defining external per-type exclusion criteria is worth considering too.

@kdkeck
Copy link

kdkeck commented Aug 14, 2015

One alternative that occurred to me after posting that was to instead use Include.NON_DEFAULT, which only requires that my type overrides Object.equals(). It still requires an annotation on the property(s) using that type, rather than an annotation only on the type, but at least it doesn't require writing a custom serializer.

@cowtowncoder cowtowncoder changed the title Allow specifying custom exclusion comparator via @JsonInclude (or similar) (2.8) Allow specifying custom exclusion comparator via @JsonInclude (or similar) Apr 22, 2016
@cowtowncoder cowtowncoder changed the title (2.8) Allow specifying custom exclusion comparator via @JsonInclude (or similar) Allow specifying custom exclusion comparator via @JsonInclude (or similar) May 5, 2016
@cowtowncoder cowtowncoder added 2.9 and removed 2.8 labels Jun 2, 2016
@madorb
Copy link

madorb commented Jun 21, 2016

+1. This would be great to be able to exclude values based on the security context. For instance when using Spring Security based on the current user's roles, we could determine whether a given property should be serialized or not.

@kdkeck
Copy link

kdkeck commented Jun 21, 2016

@madorb I would think views would be more appropriate for that use case: http://wiki.fasterxml.com/JacksonJsonViews

@madorb
Copy link

madorb commented Jun 21, 2016

I know that it can be done with views, but that puts the decision at the point of serialization, if someone forgot to use the right view it could expose sensitive information. It also doesn't play nicely with the automated serialization ala SpringMVC - where there is generally a single ObjectMapper - i'd prefer to not have to manually configure the ObjectMapper to use the appropriate view in each Controller method

@cowtowncoder
Copy link
Member Author

Planning to implement this via addition of JsonInclude.Include.CUSTOM and JsonInclude.valueFilter, which specifies filter object, of which equals(value) method is called to determine inclusion/exclusion.
Filter will be instantiated using standard HandlerInstantiator, although default will just call zero-args constructor.

Already implemented annotation side:

FasterXML/jackson-annotations#103

and now working on databind, so should be done relatively soon.

cowtowncoder added a commit that referenced this issue Oct 1, 2016
@cowtowncoder cowtowncoder changed the title Allow specifying custom exclusion comparator via @JsonInclude (or similar) Allow specifying custom exclusion comparator via @JsonInclude, using JsonInclude.Include.CUSTOM Oct 1, 2016
@cowtowncoder cowtowncoder added this to the 2.9.0 milestone Oct 1, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants