• 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 import java.util.*;
8 
9 /**
10  * Annotation that can be used to either suppress serialization of
11  * properties (during serialization), or ignore processing of
12  * JSON properties read (during deserialization).
13  *<p>
14  * Example:
15  *<pre>
16  * // to prevent specified fields from being serialized or deserialized
17  * // (i.e. not include in JSON output; or being set even if they were included)
18  * &#064;JsonIgnoreProperties({ "internalId", "secretKey" })
19  * // To ignore any unknown properties in JSON input without exception:
20  * &#064;JsonIgnoreProperties(ignoreUnknown=true)
21  *</pre>
22  *<p>
23  * Annotation can be applied both to classes and
24  * to properties. If used for both, actual set will be union of all
25  * ignorals: that is, you can only add properties to ignore, not remove
26  * or override. So you can not remove properties to ignore using
27  * per-property annotation.
28  */
29 @Target({ElementType.ANNOTATION_TYPE, ElementType.TYPE,
30     ElementType.METHOD, ElementType.CONSTRUCTOR, ElementType.FIELD})
31 @Retention(RetentionPolicy.RUNTIME)
32 @JacksonAnnotation
33 public @interface JsonIgnoreProperties
34 {
35     /**
36      * Names of properties to ignore.
37      */
value()38     public String[] value() default { };
39 
40     /**
41      * Property that defines whether it is ok to just ignore any
42      * unrecognized properties during deserialization.
43      * If true, all properties that are unrecognized -- that is,
44      * there are no setters or creators that accept them -- are
45      * ignored without warnings (although handlers for unknown
46      * properties, if any, will still be called) without
47      * exception.
48      *<p>
49      * Does not have any effect on serialization.
50      *
51      * @return True if any and all unknown properties are to be ignored without
52      *   exceptions (or other special handling); false otherwise.
53      */
ignoreUnknown()54     public boolean ignoreUnknown() default false;
55 
56     /**
57      * Property that can be enabled to allow "getters" to be used (that is,
58      * prevent ignoral of getters for properties listed in {@link #value()}).
59      * This is commonly set to support defining "read-only" properties; ones
60      * for which there is a getter, but no matching setter: in this case,
61      * properties should be ignored for deserialization but NOT serialization.
62      * Another way to think about this setting is that setting it to `true`
63      * will "disable" ignoring of getters.
64      *<p>
65      * Default value is `false`, which means that getters with matching names
66      * will be ignored.
67      *
68      * @return True if getters should be allowed (i.e. NOT ignored); false if getters
69      *    are to be ignored
70      *
71      * @since 2.6
72      */
allowGetters()73     public boolean allowGetters() default false;
74 
75     /**
76      * Property that can be enabled to allow "setters" to be used (that is,
77      * prevent ignoral of setters for properties listed in {@link #value()}).
78      * This could be used to specify "write-only" properties; ones
79      * that should not be serialized out, but that may be provided in for
80      * deserialization.
81      * Another way to think about this setting is that setting it to `true`
82      * will "disable" ignoring of setters.
83      *<p>
84      * Default value is `false`, which means that setters with matching names
85      * will be ignored.
86      *
87      *
88      * @return True if setters should be allowed (i.e. NOT ignored); false if setters
89      *    are to be ignored
90      * @since 2.6
91      */
allowSetters()92     public boolean allowSetters() default false;
93 
94     /*
95     /**********************************************************
96     /* Value class used to enclose information, allow for
97     /* merging of layered configuration settings.
98     /**********************************************************
99      */
100 
101     /**
102      * Helper class used to contain information from a single {@link JsonIgnoreProperties}
103      * annotation, as well as to provide possible overrides from non-annotation sources.
104      *
105      * @since 2.8
106      */
107     public static class Value
108         implements JacksonAnnotationValue<JsonIgnoreProperties>,
109             java.io.Serializable
110     {
111         private static final long serialVersionUID = 1L;
112 
113         /**
114          * Default instance has no explicitly ignored fields, does not ignore unknowns,
115          * does not explicitly allow getters/setters (that is, ignorals apply to both),
116          * but does use merging for combining overrides with base settings
117          */
118         protected final static Value EMPTY = new Value(Collections.<String>emptySet(),
119                 false, false, false, true);
120 
121         /**
122          * Names of properties to ignore.
123          */
124         protected final Set<String> _ignored;
125 
126         protected final boolean _ignoreUnknown;
127         protected final boolean _allowGetters;
128         protected final boolean _allowSetters;
129 
130         protected final boolean _merge;
131 
Value(Set<String> ignored, boolean ignoreUnknown, boolean allowGetters, boolean allowSetters, boolean merge)132         protected Value(Set<String> ignored, boolean ignoreUnknown,
133                 boolean allowGetters, boolean allowSetters,
134                 boolean merge)
135         {
136             if (ignored == null) {
137                 _ignored = Collections.emptySet();
138             } else {
139                 _ignored = ignored;
140             }
141             _ignoreUnknown = ignoreUnknown;
142             _allowGetters = allowGetters;
143             _allowSetters = allowSetters;
144             _merge = merge;
145         }
146 
from(JsonIgnoreProperties src)147         public static Value from(JsonIgnoreProperties src) {
148             if (src == null) {
149                 return EMPTY; // since 2.9
150             }
151             return construct(_asSet(src.value()),
152                     src.ignoreUnknown(), src.allowGetters(), src.allowSetters(),
153                 // 27-Apr-2016, tatu: No matching property in annotation because
154                 //   we don't know how to merge (so no point in pretending it's there)
155                 //   so choice is arbitrary. Probably will default to `false` fwtw:
156                     false);
157         }
158 
159         /**
160          * Factory method that may be used (although is NOT the recommended way)
161          * to construct an instance from a full set of properties. Most users would
162          * be better of starting by {@link #empty()} instance and using `withXxx()`/`withoutXxx()`
163          * methods, as this factory method may need to be changed if new properties
164          * are added in {@link JsonIgnoreProperties} annotation.
165          */
construct(Set<String> ignored, boolean ignoreUnknown, boolean allowGetters, boolean allowSetters, boolean merge)166         public static Value construct(Set<String> ignored, boolean ignoreUnknown,
167                 boolean allowGetters, boolean allowSetters,
168                 boolean merge) {
169             if (_empty(ignored, ignoreUnknown, allowGetters, allowSetters, merge)) {
170                 return EMPTY;
171             }
172             return new Value(ignored, ignoreUnknown, allowGetters, allowSetters, merge);
173         }
174 
175         /**
176          * Accessor for default instances which has "empty" settings; that is:
177          *<ul>
178          * <li>No explicitly defined fields to ignore
179          *  </li>
180          * <li>Does not ignore unknown fields
181          *  </li>
182          * <li>Does not "allow" getters if property ignored (that is, ignorals apply to both setter and getter)
183          *  </li>
184          * <li>Does not "allow" setters if property ignored (that is, ignorals apply to both setter and getter)
185          *  </li>
186          * <li>Does use merge when combining overrides to base settings, such that `true` settings
187          *   for any of the properties results in `true`, and names of fields are combined (union)
188          *  </li>
189          * </ul>
190          */
empty()191         public static Value empty() {
192             return EMPTY;
193         }
194 
195         /**
196          * Helper method that will try to combine values from two {@link Value}
197          * instances, using one as base settings, and the other as overrides
198          * to use instead of base values when defined; base values are only
199          * use if override does not specify a value (matching value is null
200          * or logically missing).
201          * Note that one or both of value instances may be `null`, directly;
202          * if both are `null`, result will also be `null`; otherwise never null.
203          */
merge(Value base, Value overrides)204         public static Value merge(Value base, Value overrides)
205         {
206             return (base == null) ? overrides
207                     : base.withOverrides(overrides);
208         }
209 
210         /**
211          * @since 2.8
212          */
mergeAll(Value... values)213         public static Value mergeAll(Value... values)
214         {
215             Value result = null;
216             for (Value curr : values) {
217                 if (curr != null) {
218                     result = (result == null)  ? curr : result.withOverrides(curr);
219                 }
220             }
221             return result;
222         }
223 
forIgnoredProperties(Set<String> propNames)224         public static Value forIgnoredProperties(Set<String> propNames) {
225             return EMPTY.withIgnored(propNames);
226         }
227 
forIgnoredProperties(String... propNames)228         public static Value forIgnoredProperties(String... propNames) {
229             if (propNames.length == 0) {
230                 return EMPTY;
231             }
232             return EMPTY.withIgnored(_asSet(propNames));
233         }
234 
forIgnoreUnknown(boolean state)235         public static Value forIgnoreUnknown(boolean state) {
236             return state ? EMPTY.withIgnoreUnknown()
237                     : EMPTY.withoutIgnoreUnknown();
238         }
239 
240         /**
241          * Mutant factory method that merges values of this value with given override
242          * values, so that any explicitly defined inclusion in overrides has precedence over
243          * settings of this value instance. If no overrides exist will return <code>this</code>
244          * instance; otherwise new {@link Value} with changed inclusion values.
245          */
withOverrides(Value overrides)246         public Value withOverrides(Value overrides) {
247             if ((overrides == null) || (overrides == EMPTY)) {
248                 return this;
249             }
250             // if non merging, we'll actually end up with just the overrides don't we?
251             // (given there's no "use default" value for anything
252             if (!overrides._merge) {
253                 return overrides;
254             }
255             if (_equals(this, overrides)) {
256                 return this;
257             }
258 
259             // Here's where mergeability needs to be checked
260             Set<String> ignored = _merge(_ignored, overrides._ignored);
261             boolean ignoreUnknown = _ignoreUnknown || overrides._ignoreUnknown;
262             boolean allowGetters = _allowGetters || overrides._allowGetters;
263             boolean allowSetters = _allowSetters || overrides._allowSetters;
264 
265             // must have 'merge=true' to get this far
266             return construct(ignored, ignoreUnknown, allowGetters, allowSetters, true);
267         }
268 
withIgnored(Set<String> ignored)269         public Value withIgnored(Set<String> ignored) {
270             return construct(ignored, _ignoreUnknown, _allowGetters, _allowSetters, _merge);
271         }
272 
withIgnored(String... ignored)273         public Value withIgnored(String... ignored) {
274             return construct(_asSet(ignored), _ignoreUnknown, _allowGetters, _allowSetters, _merge);
275         }
276 
withoutIgnored()277         public Value withoutIgnored() {
278             return construct(null, _ignoreUnknown, _allowGetters, _allowSetters, _merge);
279         }
280 
withIgnoreUnknown()281         public Value withIgnoreUnknown() {
282             return _ignoreUnknown ? this :
283                 construct(_ignored, true, _allowGetters, _allowSetters, _merge);
284         }
withoutIgnoreUnknown()285         public Value withoutIgnoreUnknown() {
286             return !_ignoreUnknown ? this :
287                 construct(_ignored, false, _allowGetters, _allowSetters, _merge);
288         }
289 
withAllowGetters()290         public Value withAllowGetters() {
291             return _allowGetters ? this :
292                 construct(_ignored, _ignoreUnknown, true, _allowSetters, _merge);
293         }
withoutAllowGetters()294         public Value withoutAllowGetters() {
295             return !_allowGetters ? this :
296                 construct(_ignored, _ignoreUnknown, false, _allowSetters, _merge);
297         }
298 
withAllowSetters()299         public Value withAllowSetters() {
300             return _allowSetters ? this :
301                 construct(_ignored, _ignoreUnknown, _allowGetters, true, _merge);
302         }
withoutAllowSetters()303         public Value withoutAllowSetters() {
304             return !_allowSetters ? this :
305                 construct(_ignored, _ignoreUnknown, _allowGetters, false, _merge);
306         }
307 
withMerge()308         public Value withMerge() {
309             return _merge ? this :
310                 construct(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, true);
311         }
312 
withoutMerge()313         public Value withoutMerge() {
314             return !_merge ? this :
315                 construct(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, false);
316         }
317 
318         @Override
valueFor()319         public Class<JsonIgnoreProperties> valueFor() {
320             return JsonIgnoreProperties.class;
321         }
322 
323         // for JDK serialization
readResolve()324         protected Object readResolve() {
325             if (_empty(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, _merge)) {
326                 return EMPTY;
327             }
328             return this;
329         }
330 
getIgnored()331         public Set<String> getIgnored() {
332             return _ignored;
333         }
334 
335         /**
336          * Method called to find names of properties to ignore when used for
337          * serialization: functionally
338          * same as {@link #getIgnored} if {@link #getAllowGetters()} is false
339          * (that is, there is "allowGetters=false" or equivalent),
340          * otherwise returns empty {@link java.util.Set}.
341          */
findIgnoredForSerialization()342         public Set<String> findIgnoredForSerialization() {
343             if (_allowGetters) {
344                 return Collections.emptySet();
345             }
346             return _ignored;
347         }
348 
349         /**
350          * Method called to find names of properties to ignore when used for
351          * serialization: functionally
352          * same as {@link #getIgnored} if {@link #getAllowSetters()} is false
353          * (that is, there is "allowSetters=false" or equivalent),
354          * otherwise returns empty {@link java.util.Set}.
355          */
findIgnoredForDeserialization()356         public Set<String> findIgnoredForDeserialization() {
357             if (_allowSetters) {
358                 return Collections.emptySet();
359             }
360             return _ignored;
361         }
362 
getIgnoreUnknown()363         public boolean getIgnoreUnknown() {
364             return _ignoreUnknown;
365         }
366 
getAllowGetters()367         public boolean getAllowGetters() {
368             return _allowGetters;
369         }
370 
getAllowSetters()371         public boolean getAllowSetters() {
372             return _allowSetters;
373         }
374 
getMerge()375         public boolean getMerge() {
376             return _merge;
377         }
378 
379         @Override
toString()380         public String toString() {
381             return String.format("JsonIgnoreProperties.Value(ignored=%s,ignoreUnknown=%s,allowGetters=%s,allowSetters=%s,merge=%s)",
382                     _ignored, _ignoreUnknown, _allowGetters, _allowSetters, _merge);
383         }
384 
385         @Override
hashCode()386         public int hashCode() {
387             return (_ignored.size())
388                     + (_ignoreUnknown ? 1 : -3)
389                     + (_allowGetters ? 3 : -7)
390                     + (_allowSetters ? 7 : -11)
391                     + (_merge ? 11 : -13)
392                             ;
393         }
394 
395         @Override
equals(Object o)396         public boolean equals(Object o) {
397             if (o == this) return true;
398             if (o == null) return false;
399             return (o.getClass() == getClass())
400                     && _equals(this, (Value) o);
401         }
402 
_equals(Value a, Value b)403         private static boolean _equals(Value a, Value b)
404         {
405             return (a._ignoreUnknown == b._ignoreUnknown)
406                     && (a._merge == b._merge)
407                     && (a._allowGetters == b._allowGetters)
408                     && (a._allowSetters == b._allowSetters)
409                     // this last just because it can be expensive
410                     && a._ignored.equals(b._ignored)
411                     ;
412         }
413 
_asSet(String[] v)414         private static Set<String> _asSet(String[] v) {
415             if (v == null || v.length == 0) {
416                 return Collections.emptySet();
417             }
418             Set<String> s = new HashSet<String>(v.length);
419             for (String str : v) {
420                 s.add(str);
421             }
422             return s;
423         }
424 
_merge(Set<String> s1, Set<String> s2)425         private static Set<String> _merge(Set<String> s1, Set<String> s2)
426         {
427             if (s1.isEmpty()) {
428                 return s2;
429             } else if (s2.isEmpty()) {
430                 return s1;
431             }
432             HashSet<String> result = new HashSet<String>(s1.size() + s2.size());
433             result.addAll(s1);
434             result.addAll(s2);
435             return result;
436         }
437 
_empty(Set<String> ignored, boolean ignoreUnknown, boolean allowGetters, boolean allowSetters, boolean merge)438         private static boolean _empty(Set<String> ignored, boolean ignoreUnknown,
439                 boolean allowGetters, boolean allowSetters, boolean merge)
440         {
441             if ((ignoreUnknown == EMPTY._ignoreUnknown)
442                     && (allowGetters == EMPTY._allowGetters)
443                     && (allowSetters == EMPTY._allowSetters)
444                     && (merge == EMPTY._merge)) {
445                 return (ignored == null || ignored.size() == 0);
446             }
447             return false;
448         }
449     }
450 }
451