![JAR search and dependency download from the Maven repository](/logo.png)
com.fasterxml.jackson.annotation.JsonIgnoreProperties Maven / Gradle / Ivy
/*
* Copyright © 2019 Dominokit
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
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;
import java.util.*;
/**
* Annotation that can be used to either suppress serialization of properties (during
* serialization), or ignore processing of JSON properties read (during deserialization).
*
* Example:
*
*
* // to prevent specified fields from being serialized or deserialized
* // (i.e. not include in JSON output; or being set even if they were included)
* @JsonIgnoreProperties({ "internalId", "secretKey" })
* // To ignore any unknown properties in JSON input without exception:
* @JsonIgnoreProperties(ignoreUnknown=true)
*
*
* Annotation can be applied both to classes and to properties. If used for both, actual set will
* be union of all ignorals: that is, you can only add properties to ignore, not remove or override.
* So you can not remove properties to ignore using per-property annotation.
*/
@Target({
ElementType.ANNOTATION_TYPE,
ElementType.TYPE,
ElementType.METHOD,
ElementType.CONSTRUCTOR,
ElementType.FIELD
})
@Retention(RetentionPolicy.RUNTIME)
@JacksonAnnotation
public @interface JsonIgnoreProperties {
/**
* Names of properties to ignore.
*
* @return String[]
*/
public String[] value() default {};
/**
* Property that defines whether it is ok to just ignore any unrecognized properties during
* deserialization. If true, all properties that are unrecognized -- that is, there are no setters
* or creators that accept them -- are ignored without warnings (although handlers for unknown
* properties, if any, will still be called) without exception.
*
*
Does not have any effect on serialization.
*
* @return boolean
*/
public boolean ignoreUnknown() default false;
/**
* Property that can be enabled to allow "getters" to be used (that is, prevent ignoral of getters
* for properties listed in {@link #value()}). This is commonly set to support defining
* "read-only" properties; ones for which there is a getter, but no matching setter: in this case,
* properties should be ignored for deserialization but NOT serialization. Another way to think
* about this setting is that setting it to `true` will "disable" ignoring of getters.
*
*
Default value is `false`, which means that getters with matching names will be ignored.
*
* @since 2.6
* @return boolean
*/
public boolean allowGetters() default false;
/**
* Property that can be enabled to allow "setters" to be used (that is, prevent ignoral of setters
* for properties listed in {@link #value()}). This could be used to specify "write-only"
* properties; ones that should not be serialized out, but that may be provided in for
* deserialization. Another way to think about this setting is that setting it to `true` will
* "disable" ignoring of setters.
*
*
Default value is `false`, which means that setters with matching names will be ignored.
*
* @since 2.6
* @return boolean
*/
public boolean allowSetters() default false;
/*
/**********************************************************
/* Value class used to enclose information, allow for
/* merging of layered configuration settings.
/**********************************************************
*/
/**
* Helper class used to contain information from a single {@link JsonIgnoreProperties} annotation,
* as well as to provide possible overrides from non-annotation sources.
*
* @since 2.8
*/
public static class Value
implements JacksonAnnotationValue, java.io.Serializable {
private static final long serialVersionUID = 1L;
/**
* Default instance has no explicitly ignored fields, does not ignore unknowns, does not
* explicitly allow getters/setters (that is, ignorals apply to both), but does use merging for
* combining overrides with base settings
*/
protected static final Value EMPTY =
new Value(Collections.emptySet(), false, false, false, true);
/** Names of properties to ignore. */
protected final Set _ignored;
protected final boolean _ignoreUnknown;
protected final boolean _allowGetters;
protected final boolean _allowSetters;
protected final boolean _merge;
protected Value(
Set ignored,
boolean ignoreUnknown,
boolean allowGetters,
boolean allowSetters,
boolean merge) {
if (ignored == null) {
_ignored = Collections.emptySet();
} else {
_ignored = ignored;
}
_ignoreUnknown = ignoreUnknown;
_allowGetters = allowGetters;
_allowSetters = allowSetters;
_merge = merge;
}
/**
* @param src {@link JsonIgnoreProperties}
* @return {@link Value}
*/
public static Value from(JsonIgnoreProperties src) {
if (src == null) {
return EMPTY; // since 2.9
}
return construct(
_asSet(src.value()),
src.ignoreUnknown(),
src.allowGetters(),
src.allowSetters(),
// 27-Apr-2016, tatu: No matching property in annotation because
// we don't know how to merge (so no point in pretending it's there)
// so choice is arbitrary. Probably will default to `false` fwtw:
false);
}
/**
* Factory method that may be used (although is NOT the recommended way) to construct an
* instance from a full set of properties. Most users would be better of starting by {@link
* #empty()} instance and using `withXxx()`/`withoutXxx()` methods, as this factory method may
* need to be changed if new properties are added in {@link JsonIgnoreProperties} annotation.
*
* @param ignored {@link Set} of {@link String}
* @param ignoreUnknown boolean
* @param allowGetters boolean
* @param allowSetters boolean
* @param merge boolean
* @return {@link Value}
*/
public static Value construct(
Set ignored,
boolean ignoreUnknown,
boolean allowGetters,
boolean allowSetters,
boolean merge) {
if (_empty(ignored, ignoreUnknown, allowGetters, allowSetters, merge)) {
return EMPTY;
}
return new Value(ignored, ignoreUnknown, allowGetters, allowSetters, merge);
}
/**
* Accessor for default instances which has "empty" settings; that is:
*
*
* - No explicitly defined fields to ignore
*
- Does not ignore unknown fields
*
- Does not "allow" getters if property ignored (that is, ignorals apply to both setter
* and getter)
*
- Does not "allow" setters if property ignored (that is, ignorals apply to both setter
* and getter)
*
- Does use merge when combining overrides to base settings, such that `true` settings for
* any of the properties results in `true`, and names of fields are combined (union)
*
*
* @return {@link Value}
*/
public static Value empty() {
return EMPTY;
}
/**
* Helper method that will try to combine values from two {@link Value} instances, using one as
* base settings, and the other as overrides to use instead of base values when defined; base
* values are only use if override does not specify a value (matching value is null or logically
* missing). Note that one or both of value instances may be `null`, directly; if both are
* `null`, result will also be `null`; otherwise never null.
*
* @param base {@link Value}
* @param overrides {@link Value}
* @return {@link Value}
*/
public static Value merge(Value base, Value overrides) {
return (base == null) ? overrides : base.withOverrides(overrides);
}
/**
* @since 2.8
* @param values {@link Value} varargs
* @return {@link Value}
*/
public static Value mergeAll(Value... values) {
Value result = null;
for (Value curr : values) {
if (curr != null) {
result = (result == null) ? curr : result.withOverrides(curr);
}
}
return result;
}
public static Value forIgnoredProperties(Set propNames) {
return EMPTY.withIgnored(propNames);
}
public static Value forIgnoredProperties(String... propNames) {
if (propNames.length == 0) {
return EMPTY;
}
return EMPTY.withIgnored(_asSet(propNames));
}
public static Value forIgnoreUnknown(boolean state) {
return state ? EMPTY.withIgnoreUnknown() : EMPTY.withoutIgnoreUnknown();
}
/**
* Mutant factory method that merges values of this value with given override values, so that
* any explicitly defined inclusion in overrides has precedence over settings of this value
* instance. If no overrides exist will return this
instance; otherwise new {@link
* Value} with changed inclusion values.
*
* @param overrides {@link Value}
* @return {@link Value}
*/
public Value withOverrides(Value overrides) {
if ((overrides == null) || (overrides == EMPTY)) {
return this;
}
// if non merging, we'll actually end up with just the overrides don't we?
// (given there's no "use default" value for anything
if (!overrides._merge) {
return overrides;
}
if (_equals(this, overrides)) {
return this;
}
// Here's where mergeability needs to be checked
Set ignored = _merge(_ignored, overrides._ignored);
boolean ignoreUnknown = _ignoreUnknown || overrides._ignoreUnknown;
boolean allowGetters = _allowGetters || overrides._allowGetters;
boolean allowSetters = _allowSetters || overrides._allowSetters;
// must have 'merge=true' to get this far
return construct(ignored, ignoreUnknown, allowGetters, allowSetters, true);
}
public Value withIgnored(Set ignored) {
return construct(ignored, _ignoreUnknown, _allowGetters, _allowSetters, _merge);
}
public Value withIgnored(String... ignored) {
return construct(_asSet(ignored), _ignoreUnknown, _allowGetters, _allowSetters, _merge);
}
public Value withoutIgnored() {
return construct(null, _ignoreUnknown, _allowGetters, _allowSetters, _merge);
}
public Value withIgnoreUnknown() {
return _ignoreUnknown
? this
: construct(_ignored, true, _allowGetters, _allowSetters, _merge);
}
public Value withoutIgnoreUnknown() {
return !_ignoreUnknown
? this
: construct(_ignored, false, _allowGetters, _allowSetters, _merge);
}
public Value withAllowGetters() {
return _allowGetters
? this
: construct(_ignored, _ignoreUnknown, true, _allowSetters, _merge);
}
public Value withoutAllowGetters() {
return !_allowGetters
? this
: construct(_ignored, _ignoreUnknown, false, _allowSetters, _merge);
}
public Value withAllowSetters() {
return _allowSetters
? this
: construct(_ignored, _ignoreUnknown, _allowGetters, true, _merge);
}
public Value withoutAllowSetters() {
return !_allowSetters
? this
: construct(_ignored, _ignoreUnknown, _allowGetters, false, _merge);
}
public Value withMerge() {
return _merge
? this
: construct(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, true);
}
public Value withoutMerge() {
return !_merge
? this
: construct(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, false);
}
@Override
public Class valueFor() {
return JsonIgnoreProperties.class;
}
// for JDK serialization
protected Object readResolve() {
if (_empty(_ignored, _ignoreUnknown, _allowGetters, _allowSetters, _merge)) {
return EMPTY;
}
return this;
}
public Set getIgnored() {
return _ignored;
}
/**
* Method called to find names of properties to ignore when used for serialization: functionally
* same as {@link #getIgnored} if {@link #getAllowGetters()} is false (that is, there is
* "allowGetters=false" or equivalent), otherwise returns empty {@link Set}.
*
* @return {@link Set} of String
*/
public Set findIgnoredForSerialization() {
if (_allowGetters) {
return Collections.emptySet();
}
return _ignored;
}
/**
* Method called to find names of properties to ignore when used for serialization: functionally
* same as {@link #getIgnored} if {@link #getAllowSetters()} is false (that is, there is
* "allowSetters=false" or equivalent), otherwise returns empty {@link Set}.
*
* @return {@link Set} of String
*/
public Set findIgnoredForDeserialization() {
if (_allowSetters) {
return Collections.emptySet();
}
return _ignored;
}
public boolean getIgnoreUnknown() {
return _ignoreUnknown;
}
public boolean getAllowGetters() {
return _allowGetters;
}
public boolean getAllowSetters() {
return _allowSetters;
}
public boolean getMerge() {
return _merge;
}
@Override
public String toString() {
return "["
+ "ignored="
+ _ignored
+ ",ignoreUnknown="
+ _ignoreUnknown
+ ",allowGetters="
+ _allowGetters
+ ",allowSetters="
+ _allowSetters
+ ",merge="
+ _merge
+ "]";
}
@Override
public int hashCode() {
return (_ignored.size())
+ (_ignoreUnknown ? 1 : -3)
+ (_allowGetters ? 3 : -7)
+ (_allowSetters ? 7 : -11)
+ (_merge ? 11 : -13);
}
@Override
public boolean equals(Object o) {
if (o == this) return true;
if (o == null) return false;
return (o.getClass() == getClass()) && _equals(this, (Value) o);
}
private static boolean _equals(Value a, Value b) {
return (a._ignoreUnknown == b._ignoreUnknown)
&& (a._merge == b._merge)
&& (a._allowGetters == b._allowGetters)
&& (a._allowSetters == b._allowSetters)
// this last just because it can be expensive
&& a._ignored.equals(b._ignored);
}
private static Set _asSet(String[] v) {
if (v == null || v.length == 0) {
return Collections.emptySet();
}
Set s = new HashSet(v.length);
for (String str : v) {
s.add(str);
}
return s;
}
private static Set _merge(Set s1, Set s2) {
if (s1.isEmpty()) {
return s2;
} else if (s2.isEmpty()) {
return s1;
}
HashSet result = new HashSet(s1.size() + s2.size());
result.addAll(s1);
result.addAll(s2);
return result;
}
private static boolean _empty(
Set ignored,
boolean ignoreUnknown,
boolean allowGetters,
boolean allowSetters,
boolean merge) {
if ((ignoreUnknown == EMPTY._ignoreUnknown)
&& (allowGetters == EMPTY._allowGetters)
&& (allowSetters == EMPTY._allowSetters)
&& (merge == EMPTY._merge)) {
return (ignored == null || ignored.size() == 0);
}
return false;
}
}
}