package com.fasterxml.jackson.annotation; import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; /** * Annotation used to indicate when value of the annotated property (when * used for a field, method or constructor parameter), or all * properties of the annotated class, is to be serialized. * Without annotation property values are always included, but by using * this annotation one can specify simple exclusion rules to reduce * amount of properties to write out. *
* Note that the main inclusion criteria (one annotated with {@link #value})
* is checked on Java object level, for the annotated type,
* and NOT on JSON output -- so even with {@link Include#NON_NULL}
* it is possible that JSON null values are output, if object reference
* in question is not `null`. An example is {@link java.util.concurrent.atomic.AtomicReference}
* instance constructed to reference null
value: such a value
* would be serialized as JSON null, and not filtered out.
*
* To base inclusion on value of contained value(s), you will typically also need
* to specify {@link #content()} annotation; for example, specifying only
* {@link #value} as {@link Include#NON_EMPTY} for a {link java.util.Map} would
* exclude Map
s with no values, but would include Map
s
* with `null` values. To exclude Map with only `null` value, you would use both
* annotations like so:
*
*public class Bean { * {@literal @JsonInclude}(value=Include.NON_EMPTY, content=Include.NON_NULL) * public Map<String,String> entries; *} ** Similarly you could Maps that only contain * "empty" elements, or "non-default" values (see {@link Include#NON_EMPTY} and * {@link Include#NON_DEFAULT} for more details). *
* In addition to `Map`s, `content` concept is also supported for referential
* types (like {@link java.util.concurrent.atomic.AtomicReference}).
* Note that `content` is NOT currently (as of Jackson 2.9) supported for
* arrays or {@link java.util.Collection}s, but supported may be added in
* future versions.
*
* @since 2.0
*/
@Target({ElementType.ANNOTATION_TYPE, ElementType.METHOD, ElementType.FIELD,
ElementType.TYPE, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonInclude
{
/**
* Inclusion rule to use for instances (values) of types (Classes) or
* properties annotated; defaults to {@link Include#ALWAYS}.
*/
public Include value() default Include.ALWAYS;
/**
* Inclusion rule to use for entries ("content") of annotated
* {@link java.util.Map}s and referential types (like
* {@link java.util.concurrent.atomic.AtomicReference});
* defaults to {@link Include#ALWAYS}.
*
* @since 2.5
*/
public Include content() default Include.ALWAYS;
/**
* Specifies type of "Filter Object" to use in case
* {@link #value} is {@link JsonInclude.Include#CUSTOM}:
* if so, an instance is created by calling HandlerInstantiator
* (of ObjectMapper
), which by default simply calls
* zero-argument constructor of the Filter Class.
*
* @since 2.9
*/
public Class> valueFilter() default Void.class;
/**
* Specifies type of "Filter Object" to use in case
* {@link #content} is {@link JsonInclude.Include#CUSTOM}:
* if so, an instance is created by calling HandlerInstantiator
* (of ObjectMapper
), which by default simply calls
* zero-argument constructor of the Filter Class.
*
* @since 2.9
*/
public Class> contentFilter() default Void.class;
/*
/**********************************************************
/* Value enumerations
/**********************************************************
*/
/**
* Enumeration used with {@link JsonInclude}
* to define which properties
* of Java Beans are to be included in serialization.
*/
public enum Include
{
/**
* Value that indicates that property is to be always included,
* independent of value of the property.
*/
ALWAYS,
/**
* Value that indicates that only properties with non-null
* values are to be included.
*/
NON_NULL,
/**
* Value that indicates that properties are included unless their value
* is:
*
* Default emptiness for all types includes: *
Null
values.isEmpty()
is called;
* length()
is called,
* and return value of 0 indicates empty String
*
* Note that this default handling can be overridden by custom
* JsonSerializer
implementation: if method isEmpty()
* is overridden, it will be called to see if non-null values are
* considered empty (null is always considered empty).
*
* Compatibility note: Jackson 2.6 included a wider range of "empty" values than * either earlier (up to 2.5) or later (2.7 and beyond) types; specifically: *
0
for `int`/`java.lang.Integer`
* and `false` for `bool`/`Boolean`)
*
* When used for a POJO, definition is that only values that differ from
* the default values of POJO properties are included. This is done
* by creating an instance of POJO using zero-argument constructor,
* and accessing property values: value is used as the default value
* by using equals()
method, except for the case where property
* has `null` value in which case straight null check is used.
*
* When NOT used for a POJO (that is, as a global default, or as property * override), definition is such that: *
equals()
method is called with value
* to serialize; if it returns true
value is excluded
* (that is, filtered out); if false
value is included.
*
* @since 2.9
*/
CUSTOM,
/**
* Pseudo-value used to indicate that the higher-level defaults make
* sense, to avoid overriding inclusion value. For example, if returned
* for a property this would use defaults for the class that contains
* property, if any defined; and if none defined for that, then
* global serialization inclusion details.
*
* @since 2.6
*/
USE_DEFAULTS
;
}
/*
/**********************************************************
/* Value class used to enclose information
/**********************************************************
*/
/**
* Helper class used to contain information from a single {@link JsonInclude}
* annotation.
*
* @since 2.6
*/
public static class Value
implements JacksonAnnotationValuethis
* instance; otherwise new {@link Value} with changed inclusion values.
*/
public Value withOverrides(Value overrides) {
if ((overrides == null) || (overrides == EMPTY)) {
return this;
}
Include vi = overrides._valueInclusion;
Include ci = overrides._contentInclusion;
Class> vf = overrides._valueFilter;
Class> cf = overrides._contentFilter;
boolean viDiff = (vi != _valueInclusion) && (vi != Include.USE_DEFAULTS);
boolean ciDiff = (ci != _contentInclusion) && (ci != Include.USE_DEFAULTS);
boolean filterDiff = (vf != _valueFilter) || (cf != _valueFilter);
if (viDiff) {
if (ciDiff) {
return new Value(vi, ci, vf, cf);
}
return new Value(vi, _contentInclusion, vf, cf);
} else if (ciDiff) {
return new Value(_valueInclusion, ci, vf, cf);
} else if (filterDiff) {
return new Value(_valueInclusion, _contentInclusion, vf, cf);
}
return this;
}
/**
* Factory method to use for constructing an instance for components
*/
public static Value construct(Include valueIncl, Include contentIncl) {
if (((valueIncl == Include.USE_DEFAULTS) || (valueIncl == null))
&& ((contentIncl == Include.USE_DEFAULTS) || (contentIncl == null))) {
return EMPTY;
}
return new Value(valueIncl, contentIncl, null, null);
}
/**
* Factory method to use for constructing an instance for components
*
* @since 2.9
*/
public static Value construct(Include valueIncl, Include contentIncl,
Class> valueFilter, Class> contentFilter)
{
if (valueFilter == Void.class) {
valueFilter = null;
}
if (contentFilter == Void.class) {
contentFilter = null;
}
if (((valueIncl == Include.USE_DEFAULTS) || (valueIncl == null))
&& ((contentIncl == Include.USE_DEFAULTS) || (contentIncl == null))
&& (valueFilter == null)
&& (contentFilter == null)
) {
return EMPTY;
}
return new Value(valueIncl, contentIncl, valueFilter, contentFilter);
}
/**
* Factory method to use for constructing an instance from instance of
* {@link JsonInclude}
*/
public static Value from(JsonInclude src) {
if (src == null) {
return EMPTY;
}
Include vi = src.value();
Include ci = src.content();
if ((vi == Include.USE_DEFAULTS) && (ci == Include.USE_DEFAULTS)) {
return EMPTY;
}
Class> vf = src.valueFilter();
if (vf == Void.class) {
vf = null;
}
Class> cf = src.contentFilter();
if (cf == Void.class) {
cf = null;
}
return new Value(vi, ci, vf, cf);
}
public Value withValueInclusion(Include incl) {
return (incl == _valueInclusion) ? this
: new Value(incl, _contentInclusion, _valueFilter, _contentFilter);
}
/**
* Mutant factory that will either
*value
as USE_DEFAULTS
* and valueFilter
to filter
(if filter not null);
* orvalue
as ALWAYS
(if filter null)
* content
as USE_DEFAULTS
* and contentFilter
to filter
(if filter not null);
* orcontent
as ALWAYS
(if filter null)
*