• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package com.fasterxml.jackson.annotation;
2 
3 import java.lang.annotation.ElementType;
4 import java.lang.annotation.Retention;
5 import java.lang.annotation.RetentionPolicy;
6 import java.lang.annotation.Target;
7 
8 /**
9  * Annotation used to indicate when value of the annotated property (when
10  * used for a field, method or constructor parameter), or all
11  * properties of the annotated class, is to be serialized.
12  * Without annotation property values are always included, but by using
13  * this annotation one can specify simple exclusion rules to reduce
14  * amount of properties to write out.
15  *<p>
16  * Note that the main inclusion criteria (one annotated with {@link #value})
17  * is checked on <b>Java object level</b>, for the annotated type,
18  * and <b>NOT</b> on JSON output -- so even with {@link Include#NON_NULL}
19  * it is possible that JSON null values are output, if object reference
20  * in question is not `null`. An example is {@link java.util.concurrent.atomic.AtomicReference}
21  * instance constructed to reference <code>null</code> value: such a value
22  * would be serialized as JSON null, and not filtered out.
23  *<p>
24  * To base inclusion on value of contained value(s), you will typically also need
25  * to specify {@link #content()} annotation; for example, specifying only
26  * {@link #value} as {@link Include#NON_EMPTY} for a {link java.util.Map} would
27  * exclude <code>Map</code>s with no values, but would include <code>Map</code>s
28  * with `null` values. To exclude Map with only `null` value, you would use both
29  * annotations like so:
30  *<pre>
31  *public class Bean {
32  *   {@literal @JsonInclude}(value=Include.NON_EMPTY, content=Include.NON_NULL)
33  *   public Map&lt;String,String&gt; entries;
34  *}
35  *</pre>
36  * Similarly you could Maps that only contain
37  * "empty" elements, or "non-default" values (see {@link Include#NON_EMPTY} and
38  * {@link Include#NON_DEFAULT} for more details).
39  *<p>
40  * In addition to `Map`s, `content` concept is also supported for referential
41  * types (like {@link java.util.concurrent.atomic.AtomicReference}).
42  * Note that `content` is NOT currently (as of Jackson 2.9) supported for
43  * arrays or {@link java.util.Collection}s, but supported may be added in
44  * future versions.
45  *
46  * @since 2.0
47  */
48 @Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD,
49     ElementType.TYPE, ElementType.PARAMETER})
50 @Retention(RetentionPolicy.RUNTIME)
51 @JacksonAnnotation
52 public @interface JsonInclude
53 {
54     /**
55      * Inclusion rule to use for instances (values) of types (Classes) or
56      * properties annotated; defaults to {@link Include#ALWAYS}.
57      */
value()58     public Include value() default Include.ALWAYS;
59 
60     /**
61      * Inclusion rule to use for entries ("content") of annotated
62      * {@link java.util.Map}s and referential types (like
63      * {@link java.util.concurrent.atomic.AtomicReference});
64      * defaults to {@link Include#ALWAYS}.
65      *
66      * @since 2.5
67      */
content()68     public Include content() default Include.ALWAYS;
69 
70     /**
71      * Specifies type of "Filter Object" to use in case
72      * {@link #value} is {@link JsonInclude.Include#CUSTOM}:
73      * if so, an instance is created by calling <code>HandlerInstantiator</code>
74      * (of <code>ObjectMapper</code>), which by default simply calls
75      * zero-argument constructor of the Filter Class.
76      *
77      * @since 2.9
78      */
valueFilter()79     public Class<?> valueFilter() default Void.class;
80 
81     /**
82      * Specifies type of "Filter Object" to use in case
83      * {@link #content} is {@link JsonInclude.Include#CUSTOM}:
84      * if so, an instance is created by calling <code>HandlerInstantiator</code>
85      * (of <code>ObjectMapper</code>), which by default simply calls
86      * zero-argument constructor of the Filter Class.
87      *
88      * @since 2.9
89      */
contentFilter()90     public Class<?> contentFilter() default Void.class;
91 
92     /*
93     /**********************************************************
94     /* Value enumerations
95     /**********************************************************
96      */
97 
98     /**
99      * Enumeration used with {@link JsonInclude}
100      * to define which properties
101      * of Java Beans are to be included in serialization.
102      */
103     public enum Include
104     {
105         /**
106          * Value that indicates that property is to be always included,
107          * independent of value of the property.
108          */
109         ALWAYS,
110 
111         /**
112          * Value that indicates that only properties with non-null
113          * values are to be included.
114          */
115         NON_NULL,
116 
117         /**
118          * Value that indicates that properties are included unless their value
119          * is:
120          *<ul>
121          *  <li>null</li>
122          *  <li>"absent" value of a referential type (like Java 8 `Optional`, or
123          *     {link java.util.concurrent.atomic.AtomicReference}); that is, something
124          *     that would not deference to a non-null value.
125          * </ul>
126          * This option is mostly used to work with "Optional"s (Java 8, Guava).
127          *
128          * @since 2.6
129          */
130         NON_ABSENT,
131 
132         /**
133          * Value that indicates that only properties with null value,
134          * or what is considered empty, are not to be included.
135          * Definition of emptiness is data type specific; see below
136          * for details on actual handling.
137          *<p>
138          * Default emptiness for all types includes:
139          *<ul>
140          * <li><code>Null</code> values.</li>
141          * <li>"Absent" values (see {@link #NON_ABSENT})</li>
142          *</ul>
143          * so that as baseline, "empty" set includes values that would be
144          * excluded by both {@link #NON_NULL} and {@link #NON_ABSENT}.
145          *<br>
146          * Beyond this base, following types have additional empty values:
147          *<ul>
148          * <li>For {@link java.util.Collection}s and {@link java.util.Map}s,
149          *    method <code>isEmpty()</code> is called;
150          *   </li>
151          * <li>For Java arrays, empty arrays are ones with length of 0
152          *   </li>
153          * <li>For Java {@link java.lang.String}s, <code>length()</code> is called,
154          *   and return value of 0 indicates empty String
155          *   </li>
156          * </ul>
157          *  and for other types, null values are excluded but other exclusions (if any).
158          *<p>
159          * Note that this default handling can be overridden by custom
160          * <code>JsonSerializer</code> implementation: if method <code>isEmpty()</code>
161          * is overridden, it will be called to see if non-null values are
162          * considered empty (null is always considered empty).
163          *<p>
164          * Compatibility note: Jackson 2.6 included a wider range of "empty" values than
165          * either earlier (up to 2.5) or later (2.7 and beyond) types; specifically:
166          *<ul>
167          * <li>Default values of primitive types (like <code>0</code> for `int`/`java.lang.Integer`
168          *  and `false` for `bool`/`Boolean`)
169          *  </li>
170          * <li>Timestamp 0 for date/time types
171          *  </li>
172          *</ul>
173          * With 2.7, definition has been tightened back to only containing types explained
174          * above (null, absent, empty String, empty containers), and now
175          * extended definition may be specified using {@link #NON_DEFAULT}.
176          */
177         NON_EMPTY,
178 
179         /**
180          * Meaning of this setting depends on context: whether annotation is
181          * specified for POJO type (class), or not. In latter case annotation
182          * is either used as the global default, or as property override.
183          *<p>
184          * When used for a POJO, definition is that only values that differ from
185          * the default values of POJO properties are included. This is done
186          * by creating an instance of POJO using zero-argument constructor,
187          * and accessing property values: value is used as the default value
188          * by using <code>equals()</code> method, except for the case where property
189          * has `null` value in which case straight null check is used.
190          *<p>
191          * When NOT used for a POJO (that is, as a global default, or as property
192          * override), definition is such that:
193          *<ul>
194          * <li>All values considered "empty" (as per {@link #NON_EMPTY}) are excluded</li>
195          * <li>Primitive/wrapper default values are excluded</li>
196          * <li>Date/time values that have timestamp (`long` value of milliseconds since
197          *   epoch, see {@link java.util.Date}) of `0L` are excluded</li>
198          * </ul>
199          */
200         NON_DEFAULT,
201 
202         /**
203          * Value that indicates that separate `filter` Object (specified by
204          * {@link JsonInclude#valueFilter} for value itself, and/or
205          * {@link JsonInclude#contentFilter} for contents of structured types)
206          * is to be used for determining inclusion criteria.
207          * Filter object's <code>equals()</code> method is called with value
208          * to serialize; if it returns <code>true</code> value is <b>excluded</b>
209          * (that is, filtered out); if <code>false</code> value is <b>included</b>.
210          *
211          * @since 2.9
212          */
213         CUSTOM,
214 
215         /**
216          * Pseudo-value used to indicate that the higher-level defaults make
217          * sense, to avoid overriding inclusion value. For example, if returned
218          * for a property this would use defaults for the class that contains
219          * property, if any defined; and if none defined for that, then
220          * global serialization inclusion details.
221          *
222          * @since 2.6
223          */
224         USE_DEFAULTS
225 
226         ;
227     }
228 
229     /*
230     /**********************************************************
231     /* Value class used to enclose information
232     /**********************************************************
233      */
234 
235     /**
236      * Helper class used to contain information from a single {@link JsonInclude}
237      * annotation.
238      *
239      * @since 2.6
240      */
241     public static class Value
242         implements JacksonAnnotationValue<JsonInclude>, // since 2.6
243             java.io.Serializable
244     {
245         private static final long serialVersionUID = 1L;
246 
247         protected final static Value EMPTY = new Value(Include.USE_DEFAULTS,
248                 Include.USE_DEFAULTS, null, null);
249 
250         protected final Include _valueInclusion;
251         protected final Include _contentInclusion;
252 
253         /**
254          * @since 2.9
255          */
256         protected final Class<?> _valueFilter;
257 
258         /**
259          * @since 2.9
260          */
261         protected final Class<?> _contentFilter;
262 
Value(JsonInclude src)263         public Value(JsonInclude src) {
264             this(src.value(), src.content(),
265                     src.valueFilter(), src.contentFilter());
266         }
267 
Value(Include vi, Include ci, Class<?> valueFilter, Class<?> contentFilter)268         protected Value(Include vi, Include ci,
269                 Class<?> valueFilter, Class<?> contentFilter) {
270             _valueInclusion = (vi == null) ? Include.USE_DEFAULTS : vi;
271             _contentInclusion = (ci == null) ? Include.USE_DEFAULTS : ci;
272             _valueFilter = (valueFilter == Void.class) ? null : valueFilter;
273             _contentFilter = (contentFilter == Void.class) ? null : contentFilter;
274         }
275 
empty()276         public static Value empty() {
277             return EMPTY;
278         }
279 
280         /**
281          * Helper method that will try to combine values from two {@link Value}
282          * instances, using one as base settings, and the other as overrides
283          * to use instead of base values when defined; base values are only
284          * use if override does not specify a value (matching value is null
285          * or logically missing).
286          * Note that one or both of value instances may be `null`, directly;
287          * if both are `null`, result will also be `null`; otherwise never null.
288          *
289          * @since 2.8
290          */
merge(Value base, Value overrides)291         public static Value merge(Value base, Value overrides)
292         {
293             return (base == null) ? overrides
294                     : base.withOverrides(overrides);
295         }
296 
297         /**
298          * @since 2.8
299          */
mergeAll(Value... values)300         public static Value mergeAll(Value... values)
301         {
302             Value result = null;
303             for (Value curr : values) {
304                 if (curr != null) {
305                     result = (result == null)  ? curr : result.withOverrides(curr);
306                 }
307             }
308             return result;
309         }
310 
311         // for JDK serialization
readResolve()312         protected Object readResolve() {
313             if ((_valueInclusion == Include.USE_DEFAULTS)
314                     && (_contentInclusion == Include.USE_DEFAULTS)
315                     && (_valueFilter == null)
316                     && (_contentFilter == null)
317                     ) {
318                 return EMPTY;
319             }
320             return this;
321         }
322 
323         /**
324          * Mutant factory method that merges values of this value with given override
325          * values, so that any explicitly defined inclusion in overrides has precedence over
326          * settings of this value instance. If no overrides exist will return <code>this</code>
327          * instance; otherwise new {@link Value} with changed inclusion values.
328          */
withOverrides(Value overrides)329         public Value withOverrides(Value overrides) {
330             if ((overrides == null) || (overrides == EMPTY)) {
331                 return this;
332             }
333             Include vi = overrides._valueInclusion;
334             Include ci = overrides._contentInclusion;
335             Class<?> vf = overrides._valueFilter;
336             Class<?> cf = overrides._contentFilter;
337 
338             boolean viDiff = (vi != _valueInclusion) && (vi != Include.USE_DEFAULTS);
339             boolean ciDiff = (ci != _contentInclusion) && (ci != Include.USE_DEFAULTS);
340             boolean filterDiff = (vf != _valueFilter) || (cf != _valueFilter);
341 
342             if (viDiff) {
343                 if (ciDiff) {
344                     return new Value(vi, ci, vf, cf);
345                 }
346                 return new Value(vi, _contentInclusion, vf, cf);
347             } else if (ciDiff) {
348                 return new Value(_valueInclusion, ci, vf, cf);
349             } else if (filterDiff) {
350                 return new Value(_valueInclusion, _contentInclusion, vf, cf);
351             }
352             return this;
353         }
354 
355         /**
356          * Factory method to use for constructing an instance for components
357          */
construct(Include valueIncl, Include contentIncl)358         public static Value construct(Include valueIncl, Include contentIncl) {
359             if (((valueIncl == Include.USE_DEFAULTS) || (valueIncl == null))
360                     && ((contentIncl == Include.USE_DEFAULTS) || (contentIncl == null))) {
361                 return EMPTY;
362             }
363             return new Value(valueIncl, contentIncl, null, null);
364         }
365 
366         /**
367          * Factory method to use for constructing an instance for components
368          *
369          * @since 2.9
370          */
construct(Include valueIncl, Include contentIncl, Class<?> valueFilter, Class<?> contentFilter)371         public static Value construct(Include valueIncl, Include contentIncl,
372                 Class<?> valueFilter, Class<?> contentFilter)
373         {
374             if (valueFilter == Void.class) {
375                 valueFilter = null;
376             }
377             if (contentFilter == Void.class) {
378                 contentFilter = null;
379             }
380             if (((valueIncl == Include.USE_DEFAULTS) || (valueIncl == null))
381                     && ((contentIncl == Include.USE_DEFAULTS) || (contentIncl == null))
382                     && (valueFilter == null)
383                     && (contentFilter == null)
384                     ) {
385                 return EMPTY;
386             }
387             return new Value(valueIncl, contentIncl, valueFilter, contentFilter);
388         }
389 
390         /**
391          * Factory method to use for constructing an instance from instance of
392          * {@link JsonInclude}
393          */
from(JsonInclude src)394         public static Value from(JsonInclude src) {
395             if (src == null) {
396                 return EMPTY;
397             }
398             Include vi = src.value();
399             Include ci = src.content();
400 
401             if ((vi == Include.USE_DEFAULTS) && (ci == Include.USE_DEFAULTS)) {
402                 return EMPTY;
403             }
404             Class<?> vf = src.valueFilter();
405             if (vf == Void.class) {
406                 vf = null;
407             }
408             Class<?> cf = src.contentFilter();
409             if (cf == Void.class) {
410                 cf = null;
411             }
412             return new Value(vi, ci, vf, cf);
413         }
414 
withValueInclusion(Include incl)415         public Value withValueInclusion(Include incl) {
416             return (incl == _valueInclusion) ? this
417                     : new Value(incl, _contentInclusion, _valueFilter, _contentFilter);
418         }
419 
420         /**
421          * Mutant factory that will either
422          *<ul>
423          * <li>Set <code>value</code> as <code>USE_DEFAULTS</code>
424          * and <code>valueFilter</code> to <code>filter</code> (if filter not null);
425          * or</li>
426          * <li>Set <code>value</code> as <code>ALWAYS</code> (if filter null)
427          *  </li>
428          *  </ul>
429          *
430          * @since 2.9
431          */
withValueFilter(Class<?> filter)432         public Value withValueFilter(Class<?> filter) {
433             Include incl;
434             if (filter == null || filter == Void.class) { // clear filter
435                 incl = Include.USE_DEFAULTS;
436                 filter = null;
437             } else {
438                 incl = Include.CUSTOM;
439             }
440             return construct(incl, _contentInclusion, filter, _contentFilter);
441         }
442 
443         /**
444          * Mutant factory that will either
445          *<ul>
446          * <li>Set <code>content</code> as <code>USE_DEFAULTS</code>
447          * and <code>contentFilter</code> to <code>filter</code> (if filter not null);
448          * or</li>
449          * <li>Set <code>content</code> as <code>ALWAYS</code> (if filter null)
450          *  </li>
451          *  </ul>
452          *
453          * @since 2.9
454          */
withContentFilter(Class<?> filter)455         public Value withContentFilter(Class<?> filter) {
456             Include incl;
457             if (filter == null || filter == Void.class) { // clear filter
458                 incl = Include.USE_DEFAULTS;
459                 filter = null;
460             } else {
461                 incl = Include.CUSTOM;
462             }
463             return construct(_valueInclusion, incl, _valueFilter, filter);
464         }
465 
withContentInclusion(Include incl)466         public Value withContentInclusion(Include incl) {
467             return (incl == _contentInclusion) ? this
468                     : new Value(_valueInclusion, incl, _valueFilter, _contentFilter);
469         }
470 
471         @Override
valueFor()472         public Class<JsonInclude> valueFor() {
473             return JsonInclude.class;
474         }
475 
getValueInclusion()476         public Include getValueInclusion() {
477             return _valueInclusion;
478         }
479 
getContentInclusion()480         public Include getContentInclusion() {
481             return _contentInclusion;
482         }
483 
getValueFilter()484         public Class<?> getValueFilter() {
485             return _valueFilter;
486         }
487 
getContentFilter()488         public Class<?> getContentFilter() {
489             return _contentFilter;
490         }
491 
492         @Override
toString()493         public String toString() {
494             StringBuilder sb = new StringBuilder(80);
495             sb.append("JsonInclude.Value(value=")
496                 .append(_valueInclusion)
497                 .append(",content=")
498                 .append(_contentInclusion);
499             if (_valueFilter != null) {
500                 sb.append(",valueFilter=").append(_valueFilter.getName()).append(".class");
501             }
502             if (_contentFilter != null) {
503                 sb.append(",contentFilter=").append(_contentFilter.getName()).append(".class");
504             }
505             return sb.append(')').toString();
506         }
507 
508         @Override
hashCode()509         public int hashCode() {
510             return (_valueInclusion.hashCode() << 2)
511                     + _contentInclusion.hashCode();
512         }
513 
514         @Override
equals(Object o)515         public boolean equals(Object o) {
516             if (o == this) return true;
517             if (o == null) return false;
518             if (o.getClass() != getClass()) return false;
519             Value other = (Value) o;
520 
521             return (other._valueInclusion == _valueInclusion)
522                     && (other._contentInclusion == _contentInclusion)
523                     && (other._valueFilter == _valueFilter)
524                     && (other._contentFilter == _contentFilter)
525                     ;
526         }
527     }
528 }
529