diff options
author | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-07-24 21:06:50 -0700 |
---|---|---|
committer | Tatu Saloranta <tatu.saloranta@iki.fi> | 2020-07-24 21:06:50 -0700 |
commit | e855ccb41a925f2b42caf773e4842355fca70206 (patch) | |
tree | 4dbb1e706b5d910d99d772d4483926790c657ac3 /src | |
parent | 65cab14b5a699ce47bf7a14c555daa444df0c16c (diff) | |
download | jackson-databind-e855ccb41a925f2b42caf773e4842355fca70206.tar.gz |
Refactoring to use separate Checker object of Map entry inclusion checks
Diffstat (limited to 'src')
4 files changed, 128 insertions, 59 deletions
diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java index 261175047..6126029a0 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java @@ -88,8 +88,19 @@ public class MapDeserializer // // Any properties to ignore if seen? protected Set<String> _ignorableProperties; + + /** + * @since 2.12 + */ protected Set<String> _includableProperties; + /** + * Helper object used for name-based filtering + * + * @since 2.12 + */ + protected IgnorePropertiesUtil.Checker _inclusionChecker; + /* /********************************************************** /* Life-cycle @@ -109,6 +120,7 @@ public class MapDeserializer _delegateDeserializer = null; _propertyBasedCreator = null; _standardStringKey = _isStdKeyDeser(mapType, keyDeser); + _inclusionChecker = null; } /** @@ -128,6 +140,7 @@ public class MapDeserializer // should we make a copy here? _ignorableProperties = src._ignorableProperties; _includableProperties = src._includableProperties; + _inclusionChecker = src._inclusionChecker; _standardStringKey = src._standardStringKey; } @@ -145,11 +158,11 @@ public class MapDeserializer * @since 2.12 */ protected MapDeserializer(MapDeserializer src, - KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, - TypeDeserializer valueTypeDeser, - NullValueProvider nuller, - Set<String> ignorable, - Set<String> includable) + KeyDeserializer keyDeser, JsonDeserializer<Object> valueDeser, + TypeDeserializer valueTypeDeser, + NullValueProvider nuller, + Set<String> ignorable, + Set<String> includable) { super(src, nuller, src._unwrapSingle); _keyDeserializer = keyDeser; @@ -161,6 +174,7 @@ public class MapDeserializer _hasDefaultCreator = src._hasDefaultCreator; _ignorableProperties = ignorable; _includableProperties = includable; + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(ignorable, includable); _standardStringKey = _isStdKeyDeser(_containerType, keyDeser); } @@ -221,15 +235,18 @@ public class MapDeserializer public void setIgnorableProperties(String[] ignorable) { _ignorableProperties = (ignorable == null || ignorable.length == 0) ? null : ArrayBuilders.arrayToSet(ignorable); + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(_ignorableProperties, _includableProperties); } public void setIgnorableProperties(Set<String> ignorable) { _ignorableProperties = (ignorable == null || ignorable.size() == 0) ? null : ignorable; + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(_ignorableProperties, _includableProperties); } public void setIncludableProperties(Set<String> includable) { _includableProperties = includable; + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(_ignorableProperties, _includableProperties); } /* @@ -514,7 +531,7 @@ public class MapDeserializer Object key = keyDes.deserializeKey(keyStr, ctxt); // And then the value... JsonToken t = p.nextToken(); - if (IgnorePropertiesUtil.shouldIgnore(keyStr, _ignorableProperties, _includableProperties)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyStr)) { p.skipChildren(); continue; } @@ -576,7 +593,7 @@ public class MapDeserializer for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); - if (IgnorePropertiesUtil.shouldIgnore(key, _ignorableProperties, _includableProperties)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(key)) { p.skipChildren(); continue; } @@ -628,7 +645,7 @@ public class MapDeserializer for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); // to get to value - if (IgnorePropertiesUtil.shouldIgnore(key, _ignorableProperties, _includableProperties)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(key)) { p.skipChildren(); // and skip it (in case of array/object) continue; } @@ -717,7 +734,7 @@ public class MapDeserializer Object key = keyDes.deserializeKey(keyStr, ctxt); // And then the value... JsonToken t = p.nextToken(); - if (IgnorePropertiesUtil.shouldIgnore(keyStr, _ignorableProperties, _includableProperties)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyStr)) { p.skipChildren(); continue; } @@ -784,7 +801,7 @@ public class MapDeserializer for (; key != null; key = p.nextFieldName()) { JsonToken t = p.nextToken(); - if (IgnorePropertiesUtil.shouldIgnore(key, _ignorableProperties, _includableProperties)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(key)) { p.skipChildren(); continue; } diff --git a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java index 4ebd088d0..5f2ab2169 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java @@ -5,9 +5,7 @@ import java.lang.reflect.Type; import java.util.*; import com.fasterxml.jackson.annotation.JsonFormat; -import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.annotation.JsonIncludeProperties; import com.fasterxml.jackson.core.*; import com.fasterxml.jackson.core.type.WritableTypeId; @@ -107,7 +105,7 @@ public class MapSerializer /* Config settings, filtering /********************************************************** */ - + /** * Set of entries to omit during serialization, if any */ @@ -115,6 +113,8 @@ public class MapSerializer /** * Set of entries to include during serialization, if null, it is ignored, empty will include nothing. + * + * @since 2.12 */ protected final Set<String> _includedEntries; @@ -145,6 +145,13 @@ public class MapSerializer */ protected final boolean _suppressNulls; + /** + * Helper object used for name-based filtering + * + * @since 2.12 + */ + protected final IgnorePropertiesUtil.Checker _inclusionChecker; + /* /********************************************************** /* Config settings, other @@ -190,6 +197,8 @@ public class MapSerializer _sortKeys = false; _suppressableValue = null; _suppressNulls = false; + + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(_ignoredEntries, _includedEntries); } /** @@ -233,6 +242,8 @@ public class MapSerializer _sortKeys = src._sortKeys; _suppressableValue = src._suppressableValue; _suppressNulls = src._suppressNulls; + + _inclusionChecker = IgnorePropertiesUtil.buildCheckerIfNeeded(_ignoredEntries, _includedEntries); } /** @@ -269,6 +280,8 @@ public class MapSerializer _sortKeys = src._sortKeys; _suppressableValue = suppressableValue; _suppressNulls = suppressNulls; + + _inclusionChecker = src._inclusionChecker; } protected MapSerializer(MapSerializer src, Object filterId, boolean sortKeys) @@ -289,6 +302,8 @@ public class MapSerializer _sortKeys = sortKeys; _suppressableValue = src._suppressableValue; _suppressNulls = src._suppressNulls; + + _inclusionChecker = src._inclusionChecker; } @Override @@ -391,9 +406,9 @@ public class MapSerializer * @since 2.8 */ public static MapSerializer construct(Set<String> ignoredEntries, JavaType mapType, - boolean staticValueType, TypeSerializer vts, - JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer, - Object filterId) + boolean staticValueType, TypeSerializer vts, + JsonSerializer<Object> keySerializer, JsonSerializer<Object> valueSerializer, + Object filterId) { return construct(ignoredEntries, null, mapType, staticValueType, vts, keySerializer, valueSerializer, filterId); } @@ -508,25 +523,19 @@ public class MapSerializer if (_neitherNull(propertyAcc, intr)) { final SerializationConfig config = provider.getConfig(); // ignorals - JsonIgnoreProperties.Value ignorals = intr.findPropertyIgnoralByName(config, propertyAcc); - if (ignorals != null){ - Set<String> newIgnored = ignorals.findIgnoredForSerialization(); - if (_nonEmpty(newIgnored)) { - ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored); - for (String str : newIgnored) { - ignored.add(str); - } + Set<String> newIgnored = intr.findPropertyIgnoralByName(config, propertyAcc).findIgnoredForSerialization(); + if (_nonEmpty(newIgnored)) { + ignored = (ignored == null) ? new HashSet<String>() : new HashSet<String>(ignored); + for (String str : newIgnored) { + ignored.add(str); } } // inclusions - JsonIncludeProperties.Value inclusions = intr.findPropertyInclusionByName(config, propertyAcc); - if (inclusions != null) { - Set<String> newIncluded = inclusions.getIncluded(); - if (newIncluded != null) { - included = (included == null) ? new HashSet<String>() : new HashSet<String>(included); - for (String str : newIncluded) { - included.add(str); - } + Set<String> newIncluded = intr.findPropertyInclusionByName(config, propertyAcc).getIncluded(); + if (newIncluded != null) { + included = (included == null) ? new HashSet<String>() : new HashSet<String>(included); + for (String str : newIncluded) { + included.add(str); } } // sort key @@ -543,13 +552,10 @@ public class MapSerializer MapSerializer mser = withResolved(property, keySer, ser, ignored, included, sortKeys); // [databind#307]: allow filtering - if (property != null) { - AnnotatedMember m = property.getMember(); - if (m != null) { - Object filterId = intr.findFilterId(m); - if (filterId != null) { - mser = mser.withFilterId(filterId); - } + if (propertyAcc != null) { + Object filterId = intr.findFilterId(propertyAcc); + if (filterId != null) { + mser = mser.withFilterId(filterId); } } JsonInclude.Value inclV = findIncludeOverrides(provider, property, Map.class); @@ -695,8 +701,6 @@ public class MapSerializer * (which can be overridden by custom implementations), but for some * dynamic types, it is possible that serializer is only resolved * during actual serialization. - * - * @since 2.0 */ public JsonSerializer<?> getKeySerializer() { return _keySerializer; @@ -776,8 +780,6 @@ public class MapSerializer return; } final JsonSerializer<Object> keySerializer = _keySerializer; - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; Object keyElem = null; try { @@ -789,7 +791,7 @@ public class MapSerializer provider.findNullKeySerializer(_keyType, _property).serialize(null, gen, provider); } else { // One twist: is entry ignorable? If so, skip - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) { + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { continue; } keySerializer.serialize(keyElem, gen, provider); @@ -822,8 +824,6 @@ public class MapSerializer serializeTypedFields(value, gen, provider, suppressableValue); return; } - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry<?,?> entry : value.entrySet()) { @@ -833,7 +833,9 @@ public class MapSerializer if (keyElem == null) { keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) continue; + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { + continue; + } keySerializer = _keySerializer; } @@ -881,13 +883,13 @@ public class MapSerializer throws IOException { final JsonSerializer<Object> keySerializer = _keySerializer; - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; final TypeSerializer typeSer = _valueTypeSerializer; for (Map.Entry<?,?> entry : value.entrySet()) { Object keyElem = entry.getKey(); - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) continue; + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { + continue; + } if (keyElem == null) { provider.findNullKeySerializer(_keyType, _property).serialize(null, gen, provider); @@ -922,15 +924,15 @@ public class MapSerializer Object suppressableValue) // since 2.5 throws IOException { - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; final MapProperty prop = new MapProperty(_valueTypeSerializer, _property); final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry<?,?> entry : value.entrySet()) { // First, serialize key; unless ignorable by key final Object keyElem = entry.getKey(); - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) continue; + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { + continue; + } JsonSerializer<Object> keySerializer; if (keyElem == null) { @@ -981,8 +983,6 @@ public class MapSerializer Object suppressableValue) // since 2.5 throws IOException { - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry<?,?> entry : value.entrySet()) { @@ -992,7 +992,9 @@ public class MapSerializer keySerializer = provider.findNullKeySerializer(_keyType, _property); } else { // One twist: is entry ignorable? If so, skip - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) continue; + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { + continue; + } keySerializer = _keySerializer; } final Object valueElem = entry.getValue(); @@ -1042,15 +1044,15 @@ public class MapSerializer Object suppressableValue) throws IOException { - final Set<String> ignored = _ignoredEntries; - final Set<String> included = _includedEntries; final MapProperty prop = new MapProperty(_valueTypeSerializer, _property); final boolean checkEmpty = (MARKER_FOR_EMPTY == suppressableValue); for (Map.Entry<?,?> entry : value.entrySet()) { // First, serialize key; unless ignorable by key final Object keyElem = entry.getKey(); - if (IgnorePropertiesUtil.shouldIgnore(keyElem, ignored, included)) continue; + if ((_inclusionChecker != null) && _inclusionChecker.shouldIgnore(keyElem)) { + continue; + } JsonSerializer<Object> keySerializer; if (keyElem == null) { diff --git a/src/main/java/com/fasterxml/jackson/databind/util/IgnorePropertiesUtil.java b/src/main/java/com/fasterxml/jackson/databind/util/IgnorePropertiesUtil.java index 88984289f..42347d9d0 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/IgnorePropertiesUtil.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/IgnorePropertiesUtil.java @@ -1,6 +1,7 @@ package com.fasterxml.jackson.databind.util; import java.util.Collection; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -30,6 +31,23 @@ public class IgnorePropertiesUtil } /** + * Factory method for creating and return a {@link Checker} instance if (and only if) + * one needed. + * + * @param toIgnore Set of property names to ignore (may be null) + * @param toInclude Set of only property names to include (if null, undefined) + * + * @return Checker, if validity checks are needed; {@code null} otherwise + */ + public static Checker buildCheckerIfNeeded(Set<String> toIgnore, Set<String> toInclude) { + // First: no-op case + if ((toInclude == null) && ((toIgnore == null) || toIgnore.isEmpty())) { + return null; + } + return Checker.construct(toIgnore, toInclude); + } + + /** * Helper that encapsulates logic for combining two sets of "included names": * default logic is to do intersection (name must be in both to be included * in result) @@ -58,4 +76,35 @@ public class IgnorePropertiesUtil } return result; } + + /** + * Helper class to encapsulate logic from static {@code shouldIgnore} method + * of util class. + */ + public final static class Checker + implements java.io.Serializable + { + private static final long serialVersionUID = 1L; + + private final Set<String> _toIgnore; + private final Set<String> _toInclude; + + private Checker(Set<String> toIgnore, Set<String> toInclude) { + if (toIgnore == null) { + toIgnore = Collections.emptySet(); + } + _toIgnore = toIgnore; + _toInclude = toInclude; + } + + public static Checker construct(Set<String> toIgnore, Set<String> toInclude) { + return new Checker(toIgnore, toInclude); + } + + // May seem odd but during serialization key is not cast up to String: + public boolean shouldIgnore(Object propertyName) { + return ((_toInclude != null) && !_toInclude.contains(propertyName)) + || _toIgnore.contains(propertyName); + } + } } diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/IncludeWithDeserTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/IncludeWithDeserTest.java index 0d10e8b07..927bdb9bb 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/IncludeWithDeserTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/IncludeWithDeserTest.java @@ -79,6 +79,7 @@ public class IncludeWithDeserTest } } + @SuppressWarnings("serial") @JsonIncludeProperties({"@class", "a"}) static class MyMap extends HashMap<String, String> { |