aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTatu Saloranta <tatu.saloranta@iki.fi>2020-07-24 21:06:50 -0700
committerTatu Saloranta <tatu.saloranta@iki.fi>2020-07-24 21:06:50 -0700
commite855ccb41a925f2b42caf773e4842355fca70206 (patch)
tree4dbb1e706b5d910d99d772d4483926790c657ac3
parent65cab14b5a699ce47bf7a14c555daa444df0c16c (diff)
downloadjackson-databind-e855ccb41a925f2b42caf773e4842355fca70206.tar.gz
Refactoring to use separate Checker object of Map entry inclusion checks
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/deser/std/MapDeserializer.java37
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/ser/std/MapSerializer.java100
-rw-r--r--src/main/java/com/fasterxml/jackson/databind/util/IgnorePropertiesUtil.java49
-rw-r--r--src/test/java/com/fasterxml/jackson/databind/deser/IncludeWithDeserTest.java1
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>
{