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<String,String> 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 */
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 */
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 */
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 */
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
263 public Value(JsonInclude src) {
264 this(src.value(), src.content(),
265 src.valueFilter(), src.contentFilter());
266 }
267
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
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 */
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 */
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
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 */
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 */
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 */
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 */
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
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 */
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 */
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
466 public Value withContentInclusion(Include incl) {
467 return (incl == _contentInclusion) ? this
468 : new Value(_valueInclusion, incl, _valueFilter, _contentFilter);
469 }
470
471 @Override
472 public Class<JsonInclude> valueFor() {
473 return JsonInclude.class;
474 }
475
476 public Include getValueInclusion() {
477 return _valueInclusion;
478 }
479
480 public Include getContentInclusion() {
481 return _contentInclusion;
482 }
483
484 public Class<?> getValueFilter() {
485 return _valueFilter;
486 }
487
488 public Class<?> getContentFilter() {
489 return _contentFilter;
490 }
491
492 @Override
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
509 public int hashCode() {
510 return (_valueInclusion.hashCode() << 2)
511 + _contentInclusion.hashCode();
512 }
513
514 @Override
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