diff options
-rw-r--r-- | release-notes/VERSION | 1 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java | 23 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java | 13 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java | 37 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java | 76 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java | 22 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java | 4 | ||||
-rw-r--r-- | src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java | 8 | ||||
-rw-r--r-- | src/test/java/com/fasterxml/jackson/databind/deser/jdk/Base64DecodingTest.java (renamed from src/test/java/com/fasterxml/jackson/databind/deser/jdk/BaseDecodingTest.java) | 2 | ||||
-rw-r--r-- | src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java | 31 |
10 files changed, 151 insertions, 66 deletions
diff --git a/release-notes/VERSION b/release-notes/VERSION index 4e8adb0aa..64f4432c6 100644 --- a/release-notes/VERSION +++ b/release-notes/VERSION @@ -21,6 +21,7 @@ Project: jackson-databind (proposed by Jan L) #1341: `DeserializationFeature.FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY` (contributed by Connor K) +#1347: Extend `ObjectMapper.configOverrides()` to allow changing visibility rules #1356: Differentiate between input and code exceptions on deserialization (suggested by Nick B) #1369: Improve `@JsonCreator` detection via `AnnotationIntrospector` diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index 66e252bee..93ee49815 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -1207,19 +1207,12 @@ public class ObjectMapper } /** - * @deprecated Since 2.6 use {@link #setVisibility(VisibilityChecker)} instead. - */ - @Deprecated - public void setVisibilityChecker(VisibilityChecker<?> vc) { - setVisibility(vc); - } - - /** - * Method for setting currently configured {@link VisibilityChecker}, + * Method for setting currently configured default {@link VisibilityChecker}, * object used for determining whether given property element * (method, field, constructor) can be auto-detected or not. - * This default checker is used if no per-class overrides - * are defined. + * This default checker is used as the base visibility: + * per-class overrides (both via annotations and per-type config overrides) + * can further change these settings. * * @since 2.6 */ @@ -1347,6 +1340,14 @@ public class ObjectMapper return this; } + /** + * @deprecated Since 2.6 use {@link #setVisibility(VisibilityChecker)} instead. + */ + @Deprecated + public void setVisibilityChecker(VisibilityChecker<?> vc) { + setVisibility(vc); + } + /* /********************************************************** /* Configuration: global-default/per-type override settings diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java index c99577269..e92aa1439 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/ConfigOverride.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.databind.cfg; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -40,6 +41,13 @@ public abstract class ConfigOverride protected JsonSetter.Value _setterInfo; /** + * Overrides for auto-detection visibility rules for this type. + * + * @since 2.9 + */ + protected JsonAutoDetect.Value _visibility; + + /** * Flag that indicates whether "is ignorable type" is specified for this type; * and if so, is it to be ignored (true) or not ignored (false); `null` is * used to indicate "not specified", in which case other configuration (class @@ -72,6 +80,11 @@ public abstract class ConfigOverride */ public JsonSetter.Value getSetterInfo() { return _setterInfo; } + /** + * @since 2.9 + */ + public JsonAutoDetect.Value getVisibility() { return _visibility; } + public JsonIgnoreProperties.Value getIgnorals() { return _ignorals; } public Boolean getIsIgnoredType() { diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java index eb67f3a21..b50a143ef 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfig.java @@ -239,17 +239,6 @@ public abstract class MapperConfig<T extends MapperConfig<T>> return NopAnnotationIntrospector.instance; } - /** - * Accessor for object used for determining whether specific property elements - * (method, constructors, fields) can be auto-detected based on - * their visibility (access modifiers). Can be changed to allow - * different minimum visibility levels for auto-detection. Note - * that this is the global handler; individual types (classes) - * can further override active checker used (using - * {@link JsonAutoDetect} annotation) - */ - public abstract VisibilityChecker<?> getDefaultVisibilityChecker(); - public final PropertyNamingStrategy getPropertyNamingStrategy() { return _base.getPropertyNamingStrategy(); } @@ -380,7 +369,7 @@ public abstract class MapperConfig<T extends MapperConfig<T>> * @return Override object to use for the type, never null (but may be empty) */ public abstract ConfigOverride getConfigOverride(Class<?> type); - + /** * Accessor for default property inclusion to use for serialization, * used unless overridden by per-type or per-property overrides. @@ -447,6 +436,30 @@ public abstract class MapperConfig<T extends MapperConfig<T>> AnnotatedClass actualClass); /** + * Accessor for object used for determining whether specific property elements + * (method, constructors, fields) can be auto-detected based on + * their visibility (access modifiers). Can be changed to allow + * different minimum visibility levels for auto-detection. Note + * that this is the global handler; individual types (classes) + * can further override active checker used (using + * {@link JsonAutoDetect} annotation) + */ + public abstract VisibilityChecker<?> getDefaultVisibilityChecker(); + + /** + * Accessor for object used for determining whether specific property elements + * (method, constructors, fields) can be auto-detected based on + * their visibility (access modifiers). This is based on global defaults + * (as would be returned by {@link #getDefaultVisibilityChecker()}, but + * then modified by possible class annotation (see {@link JsonAutoDetect}) + * and/or per-type config override (see {@link ConfigOverride#getVisibility()}). + * + * @since 2.9 + */ + public abstract VisibilityChecker<?> getDefaultVisibilityChecker(Class<?> baseType, + AnnotatedClass actualClass); + + /** * Accessor for the baseline setter info used as the global baseline, * not considering possible per-type overrides. * diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java index 9a3111092..c5e9362d1 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MapperConfigBase.java @@ -31,6 +31,17 @@ public abstract class MapperConfigBase<CFG extends ConfigFeature, private final static int DEFAULT_MAPPER_FEATURES = collectFeatureDefaults(MapperFeature.class); + /** + * @since 2.9 + */ + private final static int AUTO_DETECT_MASK = + MapperFeature.AUTO_DETECT_FIELDS.getMask() + | MapperFeature.AUTO_DETECT_GETTERS.getMask() + | MapperFeature.AUTO_DETECT_IS_GETTERS.getMask() + | MapperFeature.AUTO_DETECT_SETTERS.getMask() + | MapperFeature.AUTO_DETECT_CREATORS.getMask() + ; + /* /********************************************************** /* Immutable config @@ -576,29 +587,6 @@ public abstract class MapperConfigBase<CFG extends ConfigFeature, return _attributes; } - @Override - public VisibilityChecker<?> getDefaultVisibilityChecker() - { - VisibilityChecker<?> vchecker = _configOverrides.getDefaultVisibility(); - // then global overrides (disabling) - if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) { - vchecker = vchecker.withSetterVisibility(Visibility.NONE); - } - if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) { - vchecker = vchecker.withCreatorVisibility(Visibility.NONE); - } - if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) { - vchecker = vchecker.withGetterVisibility(Visibility.NONE); - } - if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) { - vchecker = vchecker.withIsGetterVisibility(Visibility.NONE); - } - if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) { - vchecker = vchecker.withFieldVisibility(Visibility.NONE); - } - return vchecker; - } - /* /********************************************************** /* Configuration access; default/overrides @@ -669,7 +657,47 @@ public abstract class MapperConfigBase<CFG extends ConfigFeature, } @Override - public JsonSetter.Value getDefaultSetterInfo() { + public final VisibilityChecker<?> getDefaultVisibilityChecker() + { + VisibilityChecker<?> vchecker = _configOverrides.getDefaultVisibility(); + // then global overrides (disabling) + if ((_mapperFeatures & AUTO_DETECT_MASK) != 0) { + if (!isEnabled(MapperFeature.AUTO_DETECT_FIELDS)) { + vchecker = vchecker.withFieldVisibility(Visibility.NONE); + } + if (!isEnabled(MapperFeature.AUTO_DETECT_GETTERS)) { + vchecker = vchecker.withGetterVisibility(Visibility.NONE); + } + if (!isEnabled(MapperFeature.AUTO_DETECT_IS_GETTERS)) { + vchecker = vchecker.withIsGetterVisibility(Visibility.NONE); + } + if (!isEnabled(MapperFeature.AUTO_DETECT_SETTERS)) { + vchecker = vchecker.withSetterVisibility(Visibility.NONE); + } + if (!isEnabled(MapperFeature.AUTO_DETECT_CREATORS)) { + vchecker = vchecker.withCreatorVisibility(Visibility.NONE); + } + } + return vchecker; + } + + @Override // since 2.9 + public final VisibilityChecker<?> getDefaultVisibilityChecker(Class<?> baseType, + AnnotatedClass actualClass) { + VisibilityChecker<?> vc = getDefaultVisibilityChecker(); + AnnotationIntrospector intr = getAnnotationIntrospector(); + if (intr != null) { + vc = intr.findAutoDetectVisibility(actualClass, vc); + } + ConfigOverride overrides = _configOverrides.findOverride(baseType); + if (overrides != null) { + vc = vc.withOverrides(overrides.getVisibility()); // ok to pass null + } + return vc; + } + + @Override + public final JsonSetter.Value getDefaultSetterInfo() { return _configOverrides.getDefaultSetterInfo(); } diff --git a/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java b/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java index 923086d4e..a53f6c0fc 100644 --- a/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java +++ b/src/main/java/com/fasterxml/jackson/databind/cfg/MutableConfigOverride.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.databind.cfg; +import com.fasterxml.jackson.annotation.JsonAutoDetect; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonIgnoreProperties; import com.fasterxml.jackson.annotation.JsonInclude; @@ -40,11 +41,6 @@ public class MutableConfigOverride return this; } - public MutableConfigOverride setSetterInfo(JsonSetter.Value v) { - _setterInfo = v; - return this; - } - public MutableConfigOverride setIgnorals(JsonIgnoreProperties.Value v) { _ignorals = v; return this; @@ -54,4 +50,20 @@ public class MutableConfigOverride _isIgnoredType = v; return this; } + + /** + * @since 2.9 + */ + public MutableConfigOverride setSetterInfo(JsonSetter.Value v) { + _setterInfo = v; + return this; + } + + /** + * @since 2.9 + */ + public MutableConfigOverride setVisibility(JsonAutoDetect.Value v) { + _visibility = v; + return this; + } } diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java index 7ed41668a..1fccdf2e9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -299,8 +299,8 @@ public abstract class BasicDeserializerFactory // need to construct suitable visibility checker: final DeserializationConfig config = ctxt.getConfig(); - VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker(); - vchecker = intr.findAutoDetectVisibility(beanDesc.getClassInfo(), vchecker); + VisibilityChecker<?> vchecker = config.getDefaultVisibilityChecker(beanDesc.getBeanClass(), + beanDesc.getClassInfo()); /* 24-Sep-2014, tatu: Tricky part first; need to merge resolved property information * (which has creator parameters sprinkled around) with actual creator diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java index 3f3a80fbf..6cfb97b1f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/POJOPropertiesCollector.java @@ -125,12 +125,8 @@ public class POJOPropertiesCollector _mutatorPrefix = (mutatorPrefix == null) ? "set" : mutatorPrefix; _annotationIntrospector = config.isAnnotationProcessingEnabled() ? _config.getAnnotationIntrospector() : null; - if (_annotationIntrospector == null) { - _visibilityChecker = _config.getDefaultVisibilityChecker(); - } else { - _visibilityChecker = _annotationIntrospector.findAutoDetectVisibility(classDef, - _config.getDefaultVisibilityChecker()); - } + _visibilityChecker = _config.getDefaultVisibilityChecker(type.getRawClass(), + classDef); } /* diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/BaseDecodingTest.java b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/Base64DecodingTest.java index c41cfec77..41c80fa03 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/jdk/BaseDecodingTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/jdk/Base64DecodingTest.java @@ -7,7 +7,7 @@ import com.fasterxml.jackson.databind.exc.MismatchedInputException; // Mostly for [databind#1425]; not in optimal place (as it also has // tree-access tests), but has to do for now -public class BaseDecodingTest extends BaseMapTest +public class Base64DecodingTest extends BaseMapTest { private final ObjectMapper MAPPER = objectMapper(); diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java index a8c6c1f65..9ab933d33 100644 --- a/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java +++ b/src/test/java/com/fasterxml/jackson/databind/introspect/TestAutoDetect.java @@ -31,7 +31,7 @@ public class TestAutoDetect int value; public void setValue(int x) { - throw new RuntimeException("Should NOT get called"); + throw new IllegalArgumentException("Should NOT get called"); } } @@ -67,17 +67,38 @@ public class TestAutoDetect public void testVisibilityConfigOverridesForSer() throws Exception { // first, by default, both field/method should be visible - String json = MAPPER.writeValueAsString(new Feature1347SerBean()); - assertEquals(aposToQuotes("{'field':2,'value':3}"), json); + final Feature1347SerBean input = new Feature1347SerBean(); + assertEquals(aposToQuotes("{'field':2,'value':3}"), + MAPPER.writeValueAsString(input)); ObjectMapper mapper = new ObjectMapper(); mapper.configOverride(Feature1347SerBean.class) - // !!! TODO - ; + .setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.GETTER, + Visibility.NONE)); + assertEquals(aposToQuotes("{'field':2}"), + mapper.writeValueAsString(input)); } // [databind#1347] public void testVisibilityConfigOverridesForDeser() throws Exception { + final String JSON = aposToQuotes("{'value':3}"); + + // by default, should throw exception + try { + /*Feature1347DeserBean bean =*/ + MAPPER.readValue(JSON, Feature1347DeserBean.class); + fail("Should not pass"); + } catch (JsonMappingException e) { + verifyException(e, "Should NOT get called"); + } + + // but when instructed to ignore setter, should work + ObjectMapper mapper = new ObjectMapper(); + mapper.configOverride(Feature1347DeserBean.class) + .setVisibility(JsonAutoDetect.Value.construct(PropertyAccessor.SETTER, + Visibility.NONE)); + Feature1347DeserBean result = mapper.readValue(JSON, Feature1347DeserBean.class); + assertEquals(3, result.value); } } |