diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties index 305f3b65c2..a36fc474ef 100644 --- a/.mvn/wrapper/maven-wrapper.properties +++ b/.mvn/wrapper/maven-wrapper.properties @@ -14,5 +14,5 @@ # KIND, either express or implied. See the License for the # specific language governing permissions and limitations # under the License. -distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.0/apache-maven-3.9.0-bin.zip -wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.2/apache-maven-3.9.2-bin.zip +wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.2.0/maven-wrapper-3.2.0.jar diff --git a/pom.xml b/pom.xml index 3728c5cd96..e43b8115a1 100644 --- a/pom.xml +++ b/pom.xml @@ -321,7 +321,6 @@ maven-compiler-plugin true - true 14 14 @@ -375,7 +374,6 @@ maven-compiler-plugin true - true 17 17 diff --git a/src/main/java/com/fasterxml/jackson/databind/JavaType.java b/src/main/java/com/fasterxml/jackson/databind/JavaType.java index aae3285a3d..1323b52ac5 100644 --- a/src/main/java/com/fasterxml/jackson/databind/JavaType.java +++ b/src/main/java/com/fasterxml/jackson/databind/JavaType.java @@ -254,7 +254,9 @@ public JavaType forcedNarrowBy(Class subclass) } @Deprecated // since 2.7 - protected abstract JavaType _narrow(Class subclass); + protected JavaType _narrow(Class subclass) { + return this; + } /* /********************************************************************** diff --git a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java index 0ce19c8689..b263403d64 100644 --- a/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java +++ b/src/main/java/com/fasterxml/jackson/databind/ObjectMapper.java @@ -1993,8 +1993,9 @@ public ObjectMapper activateDefaultTyping(PolymorphicTypeValidator ptv, TypeResolverBuilder typer = _constructDefaultTypeResolverBuilder(applicability, ptv); // we'll always use full class name, when using defaulting - typer = typer.init(JsonTypeInfo.Id.CLASS, null); - typer = typer.inclusion(includeAs); + JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.CLASS, includeAs, + null, null, false, null); + typer = typer.init(typeInfo, null); return setDefaultTyping(typer); } @@ -2023,9 +2024,9 @@ public ObjectMapper activateDefaultTypingAsProperty(PolymorphicTypeValidator ptv TypeResolverBuilder typer = _constructDefaultTypeResolverBuilder(applicability, ptv); // we'll always use full class name, when using defaulting - typer = typer.init(JsonTypeInfo.Id.CLASS, null); - typer = typer.inclusion(JsonTypeInfo.As.PROPERTY); - typer = typer.typeProperty(propertyName); + JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.CLASS, JsonTypeInfo.As.PROPERTY, + propertyName, null, false, null); + typer = typer.init(typeInfo, null); return setDefaultTyping(typer); } diff --git a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java index dfeaee6888..2b94b737d9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java @@ -1508,27 +1508,29 @@ protected PropertyName _findConstructorName(Annotated a) protected TypeResolverBuilder _findTypeResolver(MapperConfig config, Annotated ann, JavaType baseType) { + // since 2.16 : backporting {@link JsonTypeInfo.Value} from 3.0 + JsonTypeInfo.Value typeInfo = findPolymorphicTypeInfo(config, ann); + // First: maybe we have explicit type resolver? TypeResolverBuilder b; - JsonTypeInfo info = _findAnnotation(ann, JsonTypeInfo.class); JsonTypeResolver resAnn = _findAnnotation(ann, JsonTypeResolver.class); if (resAnn != null) { - if (info == null) { + if (typeInfo == null) { return null; } // let's not try to force access override (would need to pass // settings through if we did, since that's not doable on some platforms) b = config.typeResolverBuilderInstance(ann, resAnn.value()); } else { // if not, use standard one, if indicated by annotations - if (info == null) { + if (typeInfo == null) { return null; } // bit special; must return 'marker' to block use of default typing: - if (info.use() == JsonTypeInfo.Id.NONE) { + if (typeInfo.getIdType() == JsonTypeInfo.Id.NONE) { return _constructNoTypeResolverBuilder(); } - b = _constructStdTypeResolverBuilder(); + b = _constructStdTypeResolverBuilder(config, typeInfo, baseType); } // Does it define a custom type id resolver? JsonTypeIdResolver idResInfo = _findAnnotation(ann, JsonTypeIdResolver.class); @@ -1537,35 +1539,36 @@ protected TypeResolverBuilder _findTypeResolver(MapperConfig config, if (idRes != null) { idRes.init(baseType); } - b = b.init(info.use(), idRes); // 13-Aug-2011, tatu: One complication; external id only works for properties; // so if declared for a Class, we will need to map it to "PROPERTY" // instead of "EXTERNAL_PROPERTY" - JsonTypeInfo.As inclusion = info.include(); + JsonTypeInfo.As inclusion = typeInfo.getInclusionType(); if (inclusion == JsonTypeInfo.As.EXTERNAL_PROPERTY && (ann instanceof AnnotatedClass)) { - inclusion = JsonTypeInfo.As.PROPERTY; + typeInfo = typeInfo.withInclusionType(JsonTypeInfo.As.PROPERTY); } - b = b.inclusion(inclusion); - b = b.typeProperty(info.property()); - Class defaultImpl = info.defaultImpl(); + Class defaultImpl = typeInfo.getDefaultImpl(); // 08-Dec-2014, tatu: To deprecate `JsonTypeInfo.None` we need to use other placeholder(s); // and since `java.util.Void` has other purpose (to indicate "deser as null"), we'll instead // use `JsonTypeInfo.class` itself. But any annotation type will actually do, as they have no // valid use (cannot instantiate as default) - if (defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) { - b = b.defaultImpl(defaultImpl); + if (defaultImpl != null && defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) { + typeInfo = typeInfo.withDefaultImpl(defaultImpl); } - b = b.typeIdVisibility(info.visible()); + + b = b.init(typeInfo, idRes); return b; } /** * Helper method for constructing standard {@link TypeResolverBuilder} * implementation. + * + * @since 2.16, backported from 3.0 */ - protected StdTypeResolverBuilder _constructStdTypeResolverBuilder() { - return new StdTypeResolverBuilder(); + protected TypeResolverBuilder _constructStdTypeResolverBuilder(MapperConfig config, + JsonTypeInfo.Value typeInfo, JavaType baseType) { + return new StdTypeResolverBuilder(typeInfo); } /** diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java index d1d592866b..10dfd83f12 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -98,6 +98,24 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, */ public T init(JsonTypeInfo.Id idType, TypeIdResolver res); + /** + * Initialization method that is called right after constructing + * the builder instance, in cases where information could not be + * passed directly (for example when instantiated for an annotation) + *

+ * NOTE: This method is abstract in Jackson 3.0, at the moment of writing. + * + * @param settings Configuration settings to apply. + * + * @return Resulting builder instance (usually this builder, + * but not necessarily) + * + * @since 2.16 (backported from Jackson 3.0) + */ + default T init(JsonTypeInfo.Value settings, TypeIdResolver res) { + return init(settings.getIdType(), res); + } + /* /********************************************************** /* Methods for configuring resolver to build diff --git a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java index a98b92c0ed..32da2e1795 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/impl/StdTypeResolverBuilder.java @@ -1,5 +1,6 @@ package com.fasterxml.jackson.databind.jsontype.impl; +import com.fasterxml.jackson.databind.introspect.Annotated; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -35,6 +36,11 @@ public class StdTypeResolverBuilder */ protected boolean _typeIdVisible = false; + /** + * @since 2.16 (backported from Jackson 3.0) + */ + protected Boolean _requireTypeIdForSubtypes; + /** * Default class to use in case type information is not available * or is broken. @@ -78,10 +84,40 @@ protected StdTypeResolverBuilder(StdTypeResolverBuilder base, _customIdResolver = base._customIdResolver; _defaultImpl = defaultImpl; + _requireTypeIdForSubtypes = base._requireTypeIdForSubtypes; + } + + /** + * @since 2.16 (backported from Jackson 3.0) + */ + public StdTypeResolverBuilder(JsonTypeInfo.Value settings) { + if (settings != null) { + _idType = settings.getIdType(); + if (_idType == null) { + throw new IllegalArgumentException("idType cannot be null"); + } + _includeAs = settings.getInclusionType(); + _typeProperty = _propName(settings.getPropertyName(), _idType); + _defaultImpl = settings.getDefaultImpl(); + _typeIdVisible = settings.getIdVisible(); + _requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes(); + } + } + + /** + * @since 2.16 (backported from Jackson 3.0) + */ + protected static String _propName(String propName, JsonTypeInfo.Id idType) { + if (propName == null) { + propName = idType.getDefaultPropertyName(); + } + return propName; } public static StdTypeResolverBuilder noTypeInfoBuilder() { - return new StdTypeResolverBuilder().init(JsonTypeInfo.Id.NONE, null); + JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.NONE, null, + null, null, false, null); + return new StdTypeResolverBuilder().init(typeInfo, null); } @Override @@ -98,6 +134,31 @@ public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) return this; } + @Override + public StdTypeResolverBuilder init(JsonTypeInfo.Value settings, + TypeIdResolver idRes) + { + _customIdResolver = idRes; + + if (settings != null) { + _idType = settings.getIdType(); + if (_idType == null) { + throw new IllegalArgumentException("idType cannot be null"); + } + _includeAs = settings.getInclusionType(); + + // Let's also initialize property name as per idType default + _typeProperty = settings.getPropertyName(); + if (_typeProperty == null) { + _typeProperty = _idType.getDefaultPropertyName(); + } + _typeIdVisible = settings.getIdVisible(); + _defaultImpl = settings.getDefaultImpl(); + _requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes(); + } + return this; + } + @Override public TypeSerializer buildTypeSerializer(SerializationConfig config, JavaType baseType, Collection subtypes) @@ -436,11 +497,11 @@ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType b * * @return true if the class has type resolver annotations, false otherwise * - * @since 2.15 + * @since 2.15, using {@code ai.findPolymorphicTypeInfo(config, ac)} since 2.16. */ protected boolean _hasTypeResolver(DeserializationConfig config, JavaType baseType) { AnnotatedClass ac = AnnotatedClassResolver.resolveWithoutSuperTypes(config, baseType.getRawClass()); AnnotationIntrospector ai = config.getAnnotationIntrospector(); - return ai.findTypeResolver(config, ac, baseType) != null; + return ai.findPolymorphicTypeInfo(config, ac) != null; } } diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java b/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java index 877ebe4436..5b6d655667 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/ArrayType.java @@ -106,16 +106,6 @@ public ArrayType withStaticTyping() { /********************************************************** */ - /** - * Handling of narrowing conversions for arrays is trickier: for now, - * it is not even allowed. - */ - @Override - @Deprecated // since 2.7 - protected JavaType _narrow(Class subclass) { - return _reportUnsupported(); - } - // Should not be called, as array types in Java are not extensible; but // let's not freak out even if it is called? @Override @@ -124,10 +114,6 @@ public JavaType refine(Class contentClass, TypeBindings bindings, return null; } - private JavaType _reportUnsupported() { - throw new UnsupportedOperationException("Cannot narrow or widen array types"); - } - /* /********************************************************** /* Overridden methods diff --git a/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java b/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java index fd4179a466..64422dc5f4 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionLikeType.java @@ -89,14 +89,6 @@ public static CollectionLikeType upgradeFrom(JavaType baseType, JavaType element throw new IllegalArgumentException("Cannot upgrade from an instance of "+baseType.getClass()); } - @Override - @Deprecated // since 2.7 - protected JavaType _narrow(Class subclass) { - return new CollectionLikeType(subclass, _bindings, - _superClass, _superInterfaces, _elementType, - _valueHandler, _typeHandler, _asStatic); - } - @Override public JavaType withContentType(JavaType contentType) { if (_elementType == contentType) { diff --git a/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java b/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java index e8b176c500..ecf985dc9e 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/CollectionType.java @@ -61,13 +61,6 @@ public static CollectionType construct(Class rawType, JavaType elemT) { null, null, false); } - @Deprecated // since 2.7 - @Override - protected JavaType _narrow(Class subclass) { - return new CollectionType(subclass, _bindings, - _superClass, _superInterfaces, _elementType, null, null, _asStatic); - } - @Override public JavaType withContentType(JavaType contentType) { if (_elementType == contentType) { diff --git a/src/main/java/com/fasterxml/jackson/databind/type/IterationType.java b/src/main/java/com/fasterxml/jackson/databind/type/IterationType.java new file mode 100644 index 0000000000..1892a39533 --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/databind/type/IterationType.java @@ -0,0 +1,29 @@ +package com.fasterxml.jackson.databind.type; + +import com.fasterxml.jackson.databind.JavaType; + +/** + * Specialized {@link SimpleType} for types that are allow iteration + * over Collection(-like) types: this includes types like + * {@link java.util.Iterator}. + * Referenced type is accessible using {@link #getContentType()}. + * + * @since 2.16 + */ +public abstract class IterationType extends SimpleType +{ + private static final long serialVersionUID = 1L; + + protected final JavaType _iteratedType; + + /** + * Constructor used when upgrading into this type (via {@link #upgradeFrom}, + * the usual way for {@link IterationType}s to come into existence. + * Sets up what is considered the "base" reference type + */ + protected IterationType(TypeBase base, JavaType iteratedType) + { + super(base); + _iteratedType = iteratedType; + } +} diff --git a/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java b/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java index d745e981e4..36342b9b81 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/MapLikeType.java @@ -87,15 +87,6 @@ public static MapLikeType construct(Class rawType, JavaType keyT, null, keyT, valueT, null, null, false); } - @Deprecated - // since 2.7 - @Override - protected JavaType _narrow(Class subclass) { - return new MapLikeType(subclass, _bindings, _superClass, - _superInterfaces, _keyType, _valueType, _valueHandler, - _typeHandler, _asStatic); - } - /** * @since 2.7 */ diff --git a/src/main/java/com/fasterxml/jackson/databind/type/MapType.java b/src/main/java/com/fasterxml/jackson/databind/type/MapType.java index cec9166db3..a469298eea 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/MapType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/MapType.java @@ -57,14 +57,6 @@ public static MapType construct(Class rawType, JavaType keyT, JavaType valueT keyT, valueT, null, null, false); } - @Deprecated // since 2.7 - @Override - protected JavaType _narrow(Class subclass) { - return new MapType(subclass, _bindings, - _superClass, _superInterfaces, _keyType, _valueType, - _valueHandler, _typeHandler, _asStatic); - } - @Override public MapType withTypeHandler(Object h) { return new MapType(_class, _bindings, diff --git a/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java b/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java index 31b17de881..4ffa28fff4 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/PlaceholderForType.java @@ -83,12 +83,6 @@ public JavaType refine(Class rawType, TypeBindings bindings, JavaType superCl return _unsupported(); } - @Override - @Deprecated // since 2.7 - protected JavaType _narrow(Class subclass) { - return _unsupported(); - } - @Override public boolean isContainerType() { return false; diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java b/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java index 271c4a5458..11d2e8322b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/ReferenceType.java @@ -25,7 +25,10 @@ public class ReferenceType extends SimpleType * if being sub-classed. * * @since 2.8 + * + * @deprecated Since 2.16 */ + @Deprecated protected final JavaType _anchorType; protected ReferenceType(Class cls, TypeBindings bindings, @@ -137,10 +140,9 @@ public ReferenceType withContentValueHandler(Object h) { if (h == _referencedType.getValueHandler()) { return this; } - JavaType refdType = _referencedType.withValueHandler(h); return new ReferenceType(_class, _bindings, - _superClass, _superInterfaces, refdType, _anchorType, - _valueHandler, _typeHandler, _asStatic); + _superClass, _superInterfaces, _referencedType.withValueHandler(h), + _anchorType, _valueHandler, _typeHandler, _asStatic); } @Override @@ -174,22 +176,6 @@ protected String buildCanonicalName() return sb.toString(); } - /* - /********************************************************** - /* Narrow/widen - /********************************************************** - */ - - @Override - @Deprecated // since 2.7 - protected JavaType _narrow(Class subclass) - { - // Should we check that there is a sub-class relationship? - return new ReferenceType(subclass, _bindings, - _superClass, _superInterfaces, _referencedType, _anchorType, - _valueHandler, _typeHandler, _asStatic); - } - /* /********************************************************** /* Public API overrides @@ -237,6 +223,10 @@ public StringBuilder getGenericSignature(StringBuilder sb) /********************************************************** */ + /** + * @deprecated Since 2.16 + */ + @Deprecated public JavaType getAnchorType() { return _anchorType; } @@ -244,7 +234,10 @@ public JavaType getAnchorType() { /** * Convenience accessor that allows checking whether this is the anchor type * itself; if not, it must be one of supertypes that is also a {@link ReferenceType} + * + * @deprecated Since 2.16 */ + @Deprecated public boolean isAnchorType() { return (_anchorType == this); } diff --git a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java index b6867d347c..9cd29a8825 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/ResolvedRecursiveType.java @@ -95,12 +95,6 @@ public JavaType withStaticTyping() { return this; } - @Deprecated // since 2.7 - @Override - protected JavaType _narrow(Class subclass) { - return this; - } - @Override public JavaType refine(Class rawType, TypeBindings bindings, JavaType superClass, JavaType[] superInterfaces) { diff --git a/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java b/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java index 4669d10020..a76310db54 100644 --- a/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java +++ b/src/main/java/com/fasterxml/jackson/databind/type/SimpleType.java @@ -122,54 +122,6 @@ public static SimpleType construct(Class cls) _buildSuperClass(cls.getSuperclass(), b), null, null, null, false); } - @Override - @Deprecated - protected JavaType _narrow(Class subclass) - { - if (_class == subclass) { - return this; - } - // Should we check that there is a sub-class relationship? - // 15-Jan-2016, tatu: Almost yes, but there are some complications with - // placeholder values (`Void`, `NoClass`), so cannot quite do yet. - // TODO: fix in 2.9 - if (!_class.isAssignableFrom(subclass)) { - /* - throw new IllegalArgumentException("Class "+subclass.getName()+" not sub-type of " - +_class.getName()); - */ - return new SimpleType(subclass, _bindings, this, _superInterfaces, - _valueHandler, _typeHandler, _asStatic); - } - // Otherwise, stitch together the hierarchy. First, super-class - Class next = subclass.getSuperclass(); - if (next == _class) { // straight up parent class? Great. - return new SimpleType(subclass, _bindings, this, - _superInterfaces, _valueHandler, _typeHandler, _asStatic); - } - if ((next != null) && _class.isAssignableFrom(next)) { - JavaType superb = _narrow(next); - return new SimpleType(subclass, _bindings, superb, - null, _valueHandler, _typeHandler, _asStatic); - } - // if not found, try a super-interface - Class[] nextI = subclass.getInterfaces(); - for (Class iface : nextI) { - if (iface == _class) { // directly implemented - return new SimpleType(subclass, _bindings, null, - new JavaType[] { this }, _valueHandler, _typeHandler, _asStatic); - } - if (_class.isAssignableFrom(iface)) { // indirect, so recurse - JavaType superb = _narrow(iface); - return new SimpleType(subclass, _bindings, null, - new JavaType[] { superb }, _valueHandler, _typeHandler, _asStatic); - } - } - // should not get here but... - throw new IllegalArgumentException("Internal error: Cannot resolve sub-type for Class "+subclass.getName()+" to " - +_class.getName()); - } - @Override public JavaType withContentType(JavaType contentType) { throw new IllegalArgumentException("Simple types have no content types; cannot call withContentType()"); diff --git a/src/test-jdk14/java/com/fasterxml/jackson/databind/failing/RecordDeserialization3906Test.java b/src/test-jdk14/java/com/fasterxml/jackson/databind/failing/RecordDeserialization3906Test.java new file mode 100644 index 0000000000..dcc9a00029 --- /dev/null +++ b/src/test-jdk14/java/com/fasterxml/jackson/databind/failing/RecordDeserialization3906Test.java @@ -0,0 +1,161 @@ +package com.fasterxml.jackson.databind.failing; + +import com.fasterxml.jackson.annotation.JsonAutoDetect; +import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility; +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.PropertyAccessor; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.introspect.AnnotatedClass; +import com.fasterxml.jackson.databind.introspect.NopAnnotationIntrospector; +import com.fasterxml.jackson.databind.introspect.VisibilityChecker; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Test case that covers both failing-by-regression tests and passing tests. + *

For more details, refer to + * + * [databind#3906]: Regression: 2.15.0 breaks deserialization for records when mapper.setVisibility(ALL, NONE); + */ +public class RecordDeserialization3906Test extends BaseMapTest { + + /* + /********************************************************** + /* Set up + /********************************************************** + */ + + record Record3906(String string, int integer) { + } + + @JsonAutoDetect(creatorVisibility = Visibility.NON_PRIVATE) + record Record3906Annotated(String string, int integer) { + } + + record Record3906Creator(String string, int integer) { + @JsonCreator + Record3906Creator { + } + } + + private record PrivateRecord3906(String string, int integer) { + } + + /* + /********************************************************** + /* Failing tests that pass in 2.14 (regression) + /********************************************************** + */ + + // minimal config for reproduction + public void testEmptyJsonToRecordMiminal() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + + Record3906 recordDeser = mapper.readValue("{}", Record3906.class); + + assertEquals(new Record3906(null, 0), recordDeser); + } + + // actual config used reproduction + public void testEmptyJsonToRecordActualImpl() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); + + Record3906 recordDeser = mapper.readValue("{}", Record3906.class); + + assertEquals(new Record3906(null, 0), recordDeser); + } + + /* + /********************************************************** + /* Passing Tests : Suggested work-arounds + /* for future modifications + /********************************************************** + */ + + public void testEmptyJsonToRecordWorkAround() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + mapper.setVisibility(PropertyAccessor.ALL, Visibility.NONE); + mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.ANY); + + Record3906 recordDeser = mapper.readValue("{}", Record3906.class); + + assertEquals(new Record3906(null, 0), recordDeser); + } + + public void testEmptyJsonToRecordCreatorsVisibile() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + mapper.setVisibility(PropertyAccessor.CREATOR, Visibility.NON_PRIVATE); + + Record3906 recordDeser = mapper.readValue("{}", Record3906.class); + assertEquals(new Record3906(null, 0), recordDeser); + } + + public void testEmptyJsonToRecordUsingModule() throws JsonProcessingException { + ObjectMapper mapper = jsonMapperBuilder().addModule(new SimpleModule() { + @Override + public void setupModule(SetupContext context) { + super.setupModule(context); + context.insertAnnotationIntrospector(new NopAnnotationIntrospector() { + @Override + public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, + VisibilityChecker checker) { + return ac.getType().isRecordType() + ? checker.withCreatorVisibility(JsonAutoDetect.Visibility.NON_PRIVATE) + : checker; + } + }); + } + }).build(); + + Record3906 recordDeser = mapper.readValue("{}", Record3906.class); + assertEquals(new Record3906(null, 0), recordDeser); + } + + public void testEmptyJsonToRecordDirectAutoDetectConfig() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + + Record3906Annotated recordDeser = mapper.readValue("{}", Record3906Annotated.class); + assertEquals(new Record3906Annotated(null, 0), recordDeser); + } + + public void testEmptyJsonToRecordJsonCreator() throws JsonProcessingException { + ObjectMapper mapper = newJsonMapper(); + + Record3906Creator recordDeser = mapper.readValue("{}", Record3906Creator.class); + assertEquals(new Record3906Creator(null, 0), recordDeser); + } + + public void testEmptyJsonToRecordUsingModuleOther() throws JsonProcessingException { + ObjectMapper mapper = jsonMapperBuilder().addModule( + new SimpleModule() { + @Override + public void setupModule(SetupContext context) { + super.setupModule(context); + context.insertAnnotationIntrospector(new NopAnnotationIntrospector() { + @Override + public VisibilityChecker findAutoDetectVisibility(AnnotatedClass ac, + VisibilityChecker checker) { + if (ac.getType() == null) { + return checker; + } + if (!ac.getType().isRecordType()) { + return checker; + } + // If this is a Record, then increase the "creator" visibility again + return checker.withCreatorVisibility(Visibility.ANY); + } + }); + } + }) + .build(); + + assertEquals(new Record3906(null, 0), + mapper.readValue("{}", Record3906.class)); + assertEquals(new PrivateRecord3906(null, 0), + mapper.readValue("{}", PrivateRecord3906.class)); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/introspect/Transient3948Test.java b/src/test/java/com/fasterxml/jackson/databind/introspect/Transient3948Test.java new file mode 100644 index 0000000000..7f7859be87 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/introspect/Transient3948Test.java @@ -0,0 +1,67 @@ +package com.fasterxml.jackson.databind.introspect; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonPropertyOrder; +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import java.io.Serializable; + +public class Transient3948Test extends BaseMapTest { + + @JsonPropertyOrder(alphabetic = true) + static class Obj implements Serializable { + + private static final long serialVersionUID = -1L; + + private String a = "hello"; + + @JsonIgnore + private transient String b = "world"; + + @JsonProperty("cat") + private String c = "jackson"; + + @JsonProperty("dog") + private transient String d = "databind"; + + public String getA() { + return a; + } + + public String getB() { + return b; + } + + public String getC() { + return c; + } + + public String getD() { + return d; + } + } + + final ObjectMapper DEFAULT_MAPPER = newJsonMapper(); + + final ObjectMapper MAPPER_TRANSIENT = jsonMapperBuilder() + .configure(MapperFeature.PROPAGATE_TRANSIENT_MARKER, true) + .build(); + + public void testJsonIgnoreSerialization() throws Exception { + Obj obj1 = new Obj(); + + String json = DEFAULT_MAPPER.writeValueAsString(obj1); + + assertEquals(a2q("{'a':'hello','b':'world','cat':'jackson','dog':'databind'}"), json); + } + + public void testJsonIgnoreSerializationTransient() throws Exception { + Obj obj1 = new Obj(); + + String json = MAPPER_TRANSIENT.writeValueAsString(obj1); + + assertEquals(a2q("{'a':'hello','cat':'jackson','dog':'databind'}"), json); + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java index 2765ddb9d3..a34d787b4f 100644 --- a/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java +++ b/src/test/java/com/fasterxml/jackson/databind/ser/jdk/MapKeySerializationTest.java @@ -256,6 +256,27 @@ public void testUnWrappedMapWithDefaultType() throws Exception{ assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json); } + public void testUnWrappedMapWithDefaultTypeWithValue() throws Exception { + final ObjectMapper mapper = new ObjectMapper(); + SimpleModule mod = new SimpleModule("test"); + mod.addKeySerializer(ABC.class, new ABCKeySerializer()); + mapper.registerModule(mod); + + TypeResolverBuilder typer = ObjectMapper.DefaultTypeResolverBuilder.construct( + ObjectMapper.DefaultTyping.NON_FINAL, mapper.getPolymorphicTypeValidator()); + JsonTypeInfo.Value typeInfo = JsonTypeInfo.Value.construct(JsonTypeInfo.Id.NAME, JsonTypeInfo.As.PROPERTY, + null, null, true, null); + typer.init(typeInfo, null); + mapper.setDefaultTyping(typer); + + Map stuff = new HashMap(); + stuff.put(ABC.B, "bar"); + String json = mapper.writerFor(new TypeReference>() { + }) + .writeValueAsString(stuff); + assertEquals("{\"@type\":\"HashMap\",\"xxxB\":\"bar\"}", json); + } + // [databind#1552] public void testMapsWithBinaryKeys() throws Exception { diff --git a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java index 2944e50c42..d70979d73e 100644 --- a/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java +++ b/src/test/java/com/fasterxml/jackson/databind/type/TestJavaType.java @@ -117,10 +117,6 @@ public void testDeprecated() assertNull(baseType.getContentValueHandler()); assertFalse(baseType.hasValueHandler()); assertFalse(baseType.hasHandlers()); - - assertSame(baseType, baseType.forcedNarrowBy(BaseType.class)); - JavaType sub = baseType.forcedNarrowBy(SubType.class); - assertTrue(sub.hasRawClass(SubType.class)); } public void testArrayType()