From 380f007c7113af060340d92259bc889d6eefd299 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Fri, 21 Apr 2023 08:26:01 +0900 Subject: [PATCH 1/9] Feature --- pom.xml | 2 +- .../JacksonAnnotationIntrospector.java | 2 + .../jsontype/TypeResolverBuilder.java | 15 +++ .../jsontype/impl/StdTypeResolverBuilder.java | 24 +++- ...verrideStrictTypeInfoHandling3877Test.java | 116 ++++++++++++++++++ 5 files changed, 156 insertions(+), 3 deletions(-) create mode 100644 src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java diff --git a/pom.xml b/pom.xml index 3728c5cd96..9f251cd974 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ usage seems to benefit from actually specifying version here in case it is dependent on transitively --> - ${jackson.version.annotations} + 2.16.0-SNAPSHOT-joohyukkim com.fasterxml.jackson.core 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 495d990b2c..9fda975c48 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java @@ -1547,6 +1547,8 @@ protected TypeResolverBuilder _findTypeResolver(MapperConfig config, b = b.defaultImpl(defaultImpl); } b = b.typeIdVisibility(info.visible()); + // [databind#3877]: allow configuration of per-type strict type handling + b.requireTypeIdForSubtypes(info.requireTypeIdForSubtypes().asBoolean()); return b; } 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..aa53027daf 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; +import com.fasterxml.jackson.annotation.OptBoolean; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializationConfig; @@ -153,6 +154,20 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, */ public T typeIdVisibility(boolean isVisible); + /** + * Sets {@link Boolean} value provided by {@link OptBoolean#asBoolean()} of + * configured {@link JsonTypeInfo#requireTypeIdForSubtypes}. + * If not {@code null}, this value overrides the global configuration of + * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * + * WARNING: This method will be abstract in Jackson 3.0. + * + * @since 2.16 + */ + public default void requireTypeIdForSubtypes(Boolean requireTypeId) { + return; + } + /* /********************************************************************** /* Mutant factories (2.13+) 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..72eee01669 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 @@ -45,6 +45,15 @@ public class StdTypeResolverBuilder protected TypeIdResolver _customIdResolver; + /** + * Boolean value configured through {@link JsonTypeInfo#requireTypeIdForSubtypes}. + * If not {@code null}, this value overrides the global configuration of + * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * + * @since 2.16 + */ + protected Boolean _requireTypeIdForSubtypes; + /* /********************************************************** /* Construction, initialization, actual building @@ -275,6 +284,11 @@ public StdTypeResolverBuilder withDefaultImpl(Class defaultImpl) { return new StdTypeResolverBuilder(this, defaultImpl); } + @Override + public void requireTypeIdForSubtypes(Boolean requireTypeId) { + _requireTypeIdForSubtypes = requireTypeId; + } + /* /********************************************************** /* Accessors @@ -405,7 +419,9 @@ protected boolean allowPrimitiveTypes(MapperConfig config, /** * Determines whether strict type ID handling should be used for this type or not. - * This will be enabled when either the type has type resolver annotations or if + * This will return as configured by {@link JsonTypeInfo#requireTypeIdForSubtypes()} + * if the value is not {@code OptBoolean.DEFAULT}. + * Otherwise,This will be enabled when either the type has type resolver annotations or if * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES} * is enabled. * @@ -415,9 +431,13 @@ protected boolean allowPrimitiveTypes(MapperConfig config, * @return {@code true} if the class has type resolver annotations, or the strict * handling feature is enabled, {@code false} otherwise. * - * @since 2.15 + * @since 2.16 */ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType baseType) { + // [databind#3877]: allow configuration of per-type strict type handling + if (_requireTypeIdForSubtypes != null && baseType.isConcrete()) { + return _requireTypeIdForSubtypes; + } if (config.isEnabled(MapperFeature.REQUIRE_TYPE_ID_FOR_SUBTYPES)) { return true; } diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java new file mode 100644 index 0000000000..a279ce8189 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java @@ -0,0 +1,116 @@ +package com.fasterxml.jackson.databind.jsontype; + +import com.fasterxml.jackson.annotation.JsonSubTypes; +import com.fasterxml.jackson.annotation.JsonTypeInfo; +import com.fasterxml.jackson.annotation.JsonTypeInfo.Id; +import com.fasterxml.jackson.annotation.OptBoolean; +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.MapperFeature; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.exc.InvalidTypeIdException; +import com.fasterxml.jackson.databind.json.JsonMapper; + +// [databind#3877]: allow configuration of per-type strict type handling +public class OverrideStrictTypeInfoHandling3877Test extends BaseMapTest { + + /* + /********************************************************** + /* Set Up + /********************************************************** + */ + + @JsonTypeInfo(use = Id.NAME, requireTypeIdForSubtypes = OptBoolean.DEFAULT) + @JsonSubTypes({ + @JsonSubTypes.Type(value = DoDefaultCommand.class, name = "do-default")}) + interface DefaultCommand {} + + static class DoDefaultCommand implements DefaultCommand {} + + @JsonTypeInfo(use = Id.NAME, requireTypeIdForSubtypes = OptBoolean.TRUE) + @JsonSubTypes({ + @JsonSubTypes.Type(value = DoTrueCommand.class, name = "do-true")}) + interface TrueCommand {} + + static class DoTrueCommand implements TrueCommand {} + + @JsonTypeInfo(use = Id.NAME, requireTypeIdForSubtypes = OptBoolean.FALSE) + @JsonSubTypes({ + @JsonSubTypes.Type(value = DoFalseCommand.class, name = "do-false")}) + interface FalseCommand {} + + static class DoFalseCommand implements FalseCommand {} + + /* + /********************************************************** + /* Tests + /********************************************************** + */ + + private final ObjectMapper ENABLED_MAPPER = JsonMapper.builder().enable(MapperFeature.REQUIRE_TYPE_ID_FOR_SUBTYPES).build(); + private final ObjectMapper DISABLED_MAPPER = JsonMapper.builder().disable(MapperFeature.REQUIRE_TYPE_ID_FOR_SUBTYPES).build(); + private final ObjectMapper DEFAULT_MAPPER = JsonMapper.builder().build(); + + public void testMissingTypeId() throws Exception { + // super types fail on missing-id no matter what + verifyFailureMissingTypeId("{}", FalseCommand.class, ENABLED_MAPPER); + verifyFailureMissingTypeId("{}", FalseCommand.class, DEFAULT_MAPPER); + verifyFailureMissingTypeId("{}", FalseCommand.class, DISABLED_MAPPER); + verifyFailureMissingTypeId("{}", TrueCommand.class, ENABLED_MAPPER); + verifyFailureMissingTypeId("{}", TrueCommand.class, DEFAULT_MAPPER); + verifyFailureMissingTypeId("{}", TrueCommand.class, DISABLED_MAPPER); + verifyFailureMissingTypeId("{}", DefaultCommand.class, ENABLED_MAPPER); + verifyFailureMissingTypeId("{}", DefaultCommand.class, DEFAULT_MAPPER); + verifyFailureMissingTypeId("{}", DefaultCommand.class, DISABLED_MAPPER); + + // overrides : to require type id + verifySuccessWithNonNullAndType("{}", DoFalseCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType("{}", DoFalseCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType("{}", DoFalseCommand.class, DISABLED_MAPPER); + // overrides : do not require type id + verifyFailureMissingTypeId("{}", DoTrueCommand.class, ENABLED_MAPPER); + verifyFailureMissingTypeId("{}", DoTrueCommand.class, DEFAULT_MAPPER); + verifyFailureMissingTypeId("{}", DoTrueCommand.class, DISABLED_MAPPER); + // overrides : defaults + verifyFailureMissingTypeId("{}", DoDefaultCommand.class, ENABLED_MAPPER); + verifyFailureMissingTypeId("{}", DoDefaultCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType("{}", DoDefaultCommand.class, DISABLED_MAPPER); + } + + public void testSuccessWithTypeId() throws Exception { + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, DISABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), DoFalseCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), DoFalseCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), DoFalseCommand.class, DISABLED_MAPPER); + + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), TrueCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), TrueCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), TrueCommand.class, DISABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), DoTrueCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), DoTrueCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-true'}"), DoTrueCommand.class, DISABLED_MAPPER); + + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DefaultCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DefaultCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DefaultCommand.class, DISABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DoDefaultCommand.class, ENABLED_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DoDefaultCommand.class, DEFAULT_MAPPER); + verifySuccessWithNonNullAndType(a2q("{'@type': 'do-default'}"), DoDefaultCommand.class, DISABLED_MAPPER); + } + + private void verifySuccessWithNonNullAndType(String json, Class clazz, ObjectMapper om) throws Exception { + T bean = om.readValue(json, clazz); + assertNotNull(bean); + assertType(bean, clazz); + } + + private void verifyFailureMissingTypeId(String json, Class clazz, ObjectMapper om) throws Exception { + try { + om.readValue(json, clazz); + fail("Should not pass"); + } catch (InvalidTypeIdException e) { + verifyException(e, "missing type id property '@type'"); + } + } +} From e79567cbab4f9b39899598ecfee6085c1c124cd5 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Fri, 21 Apr 2023 19:43:15 +0900 Subject: [PATCH 2/9] Improve JavaDoc --- .../jackson/databind/jsontype/TypeResolverBuilder.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) 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 aa53027daf..c8128d3d31 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -155,11 +155,10 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, public T typeIdVisibility(boolean isVisible); /** - * Sets {@link Boolean} value provided by {@link OptBoolean#asBoolean()} of - * configured {@link JsonTypeInfo#requireTypeIdForSubtypes}. - * If not {@code null}, this value overrides the global configuration of - * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. - * + * Method for specifying whether strict type ID handling should be used for this type or not. + * This is per-type override of {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * Sets {@link Boolean} value provided by {@link OptBoolean#asBoolean()} of configured {@link JsonTypeInfo#requireTypeIdForSubtypes}. + *

* WARNING: This method will be abstract in Jackson 3.0. * * @since 2.16 From bbac070449014d92bb271677274b76c8a23edad4 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Mon, 24 Apr 2023 20:29:02 +0900 Subject: [PATCH 3/9] Clean up changes --- pom.xml | 2 +- .../databind/jsontype/impl/StdTypeResolverBuilder.java | 10 +++++----- .../OverrideStrictTypeInfoHandling3877Test.java | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 9f251cd974..3728c5cd96 100644 --- a/pom.xml +++ b/pom.xml @@ -80,7 +80,7 @@ usage seems to benefit from actually specifying version here in case it is dependent on transitively --> - 2.16.0-SNAPSHOT-joohyukkim + ${jackson.version.annotations} com.fasterxml.jackson.core 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 72eee01669..715be77d88 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 @@ -47,7 +47,7 @@ public class StdTypeResolverBuilder /** * Boolean value configured through {@link JsonTypeInfo#requireTypeIdForSubtypes}. - * If not {@code null}, this value overrides the global configuration of + * If this value is not {@code null}, this value overrides the global configuration of * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. * * @since 2.16 @@ -419,9 +419,9 @@ protected boolean allowPrimitiveTypes(MapperConfig config, /** * Determines whether strict type ID handling should be used for this type or not. - * This will return as configured by {@link JsonTypeInfo#requireTypeIdForSubtypes()} - * if the value is not {@code OptBoolean.DEFAULT}. - * Otherwise,This will be enabled when either the type has type resolver annotations or if + * This will be enabld as configured by {@link JsonTypeInfo#requireTypeIdForSubtypes()} + * unless its value is {@code OptBoolean.DEFAULT}. Otherwise, + * this will be enabled when either the type has type resolver annotations or if * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES} * is enabled. * @@ -431,7 +431,7 @@ protected boolean allowPrimitiveTypes(MapperConfig config, * @return {@code true} if the class has type resolver annotations, or the strict * handling feature is enabled, {@code false} otherwise. * - * @since 2.16 + * @since 2.15 */ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType baseType) { // [databind#3877]: allow configuration of per-type strict type handling diff --git a/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java b/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java index a279ce8189..b54c503c6c 100644 --- a/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java +++ b/src/test/java/com/fasterxml/jackson/databind/jsontype/OverrideStrictTypeInfoHandling3877Test.java @@ -76,7 +76,7 @@ public void testMissingTypeId() throws Exception { verifySuccessWithNonNullAndType("{}", DoDefaultCommand.class, DISABLED_MAPPER); } - public void testSuccessWithTypeId() throws Exception { + public void testSuccessWhenTypeIdIsProvided() throws Exception { verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, ENABLED_MAPPER); verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, DEFAULT_MAPPER); verifySuccessWithNonNullAndType(a2q("{'@type': 'do-false'}"), FalseCommand.class, DISABLED_MAPPER); From 8484533e8c35eeeb3a179e942f6c0fbf9d630076 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Mon, 24 Apr 2023 20:44:32 +0900 Subject: [PATCH 4/9] Update StdTypeResolverBuilder.java --- .../jackson/databind/jsontype/impl/StdTypeResolverBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 715be77d88..239605952f 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 @@ -434,7 +434,7 @@ protected boolean allowPrimitiveTypes(MapperConfig config, * @since 2.15 */ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType baseType) { - // [databind#3877]: allow configuration of per-type strict type handling + // [databind#3877]: since 2.16, allow configuration of per-type strict type handling if (_requireTypeIdForSubtypes != null && baseType.isConcrete()) { return _requireTypeIdForSubtypes; } From e361300a8b20436a516ea95b5579192bbf46bc5d Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Tue, 16 May 2023 19:11:17 +0900 Subject: [PATCH 5/9] Improve JavaDoc (though subjective ...) --- .../jackson/databind/jsontype/TypeResolverBuilder.java | 6 ++---- .../databind/jsontype/impl/StdTypeResolverBuilder.java | 5 +++-- 2 files changed, 5 insertions(+), 6 deletions(-) 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 c8128d3d31..e0f0554c75 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -156,10 +156,8 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, /** * Method for specifying whether strict type ID handling should be used for this type or not. - * This is per-type override of {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. - * Sets {@link Boolean} value provided by {@link OptBoolean#asBoolean()} of configured {@link JsonTypeInfo#requireTypeIdForSubtypes}. - *

- * WARNING: This method will be abstract in Jackson 3.0. + * Parameter {@code Boolean requireTypeId} is provided by {@link JsonTypeInfo#requireTypeIdForSubtypes()}. + * Configuration using this method will override {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. * * @since 2.16 */ 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 239605952f..7840f28de0 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 @@ -420,7 +420,8 @@ protected boolean allowPrimitiveTypes(MapperConfig config, /** * Determines whether strict type ID handling should be used for this type or not. * This will be enabld as configured by {@link JsonTypeInfo#requireTypeIdForSubtypes()} - * unless its value is {@code OptBoolean.DEFAULT}. Otherwise, + * unless its value is {@link com.fasterxml.jackson.annotation.OptBoolean#DEFAULT}. + * In case the value of {@link JsonTypeInfo#requireTypeIdForSubtypes()} is {@code OptBoolean.DEFAULT}, * this will be enabled when either the type has type resolver annotations or if * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES} * is enabled. @@ -434,7 +435,7 @@ protected boolean allowPrimitiveTypes(MapperConfig config, * @since 2.15 */ protected boolean _strictTypeIdHandling(DeserializationConfig config, JavaType baseType) { - // [databind#3877]: since 2.16, allow configuration of per-type strict type handling + // [databind#3877]: per-type strict type handling, since 2.16 if (_requireTypeIdForSubtypes != null && baseType.isConcrete()) { return _requireTypeIdForSubtypes; } From 6968ab3556f0843ca648bf6099b809cbd28d81ea Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Tue, 16 May 2023 19:22:43 +0900 Subject: [PATCH 6/9] Improve JavaDoc of TypeResolverBuilder --- .../jackson/databind/jsontype/TypeResolverBuilder.java | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) 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 e0f0554c75..9a7d317a0b 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -155,14 +155,18 @@ public TypeDeserializer buildTypeDeserializer(DeserializationConfig config, public T typeIdVisibility(boolean isVisible); /** - * Method for specifying whether strict type ID handling should be used for this type or not. + * Specifies whether strict type ID handling should be used for this type. * Parameter {@code Boolean requireTypeId} is provided by {@link JsonTypeInfo#requireTypeIdForSubtypes()}. - * Configuration using this method will override {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * This configuration overrides the global setting defined by + * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * + * @param requireTypeId {@code true} to enforce type ID handling, {@code false} otherwise. + * If {@code null}, the global setting will be used. * * @since 2.16 */ public default void requireTypeIdForSubtypes(Boolean requireTypeId) { - return; + // no-op } /* From 52c6fc63f8549bc87b91581a882b0a14eac9fdaf Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 18 May 2023 20:59:10 +0900 Subject: [PATCH 7/9] Improve comment about null checking --- .../databind/introspect/JacksonAnnotationIntrospector.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 9fda975c48..3a75802de8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java @@ -1547,7 +1547,8 @@ protected TypeResolverBuilder _findTypeResolver(MapperConfig config, b = b.defaultImpl(defaultImpl); } b = b.typeIdVisibility(info.visible()); - // [databind#3877]: allow configuration of per-type strict type handling + // [databind#3877]: per-type strict type handling. No need for null-checking of {@code OptBoolean.asBoolean()} + // value, because it will be done during construction of deserializer. b.requireTypeIdForSubtypes(info.requireTypeIdForSubtypes().asBoolean()); return b; } From 32860a462fed2e1a84bb6753231026f5757f995a Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Sat, 27 May 2023 12:50:28 +0900 Subject: [PATCH 8/9] Update changes accordingly. --- .../jsontype/TypeResolverBuilder.java | 16 ------------ .../jsontype/impl/StdTypeResolverBuilder.java | 25 +++++++------------ 2 files changed, 9 insertions(+), 32 deletions(-) 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 902b0e1c7b..10dfd83f12 100644 --- a/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java +++ b/src/main/java/com/fasterxml/jackson/databind/jsontype/TypeResolverBuilder.java @@ -4,7 +4,6 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo; import com.fasterxml.jackson.annotation.JsonTypeInfo.As; -import com.fasterxml.jackson.annotation.OptBoolean; import com.fasterxml.jackson.databind.DeserializationConfig; import com.fasterxml.jackson.databind.JavaType; import com.fasterxml.jackson.databind.SerializationConfig; @@ -172,21 +171,6 @@ default T init(JsonTypeInfo.Value settings, TypeIdResolver res) { */ public T typeIdVisibility(boolean isVisible); - /** - * Specifies whether strict type ID handling should be used for this type. - * Parameter {@code Boolean requireTypeId} is provided by {@link JsonTypeInfo#requireTypeIdForSubtypes()}. - * This configuration overrides the global setting defined by - * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. - * - * @param requireTypeId {@code true} to enforce type ID handling, {@code false} otherwise. - * If {@code null}, the global setting will be used. - * - * @since 2.16 - */ - public default void requireTypeIdForSubtypes(Boolean requireTypeId) { - // no-op - } - /* /********************************************************************** /* Mutant factories (2.13+) 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 9423684177..e7af475599 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,6 +1,5 @@ package com.fasterxml.jackson.databind.jsontype.impl; -import com.fasterxml.jackson.databind.introspect.Annotated; import java.util.Collection; import com.fasterxml.jackson.annotation.JsonTypeInfo; @@ -37,6 +36,11 @@ public class StdTypeResolverBuilder protected boolean _typeIdVisible = false; /** + * + * Boolean value configured through {@link JsonTypeInfo#requireTypeIdForSubtypes}. + * If this value is not {@code null}, this value overrides the global configuration of + * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. + * * @since 2.16 (backported from Jackson 3.0) */ protected Boolean _requireTypeIdForSubtypes; @@ -51,15 +55,6 @@ public class StdTypeResolverBuilder protected TypeIdResolver _customIdResolver; - /** - * Boolean value configured through {@link JsonTypeInfo#requireTypeIdForSubtypes}. - * If this value is not {@code null}, this value overrides the global configuration of - * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. - * - * @since 2.16 - */ - protected Boolean _requireTypeIdForSubtypes; - /* /********************************************************** /* Construction, initialization, actual building @@ -108,7 +103,7 @@ public StdTypeResolverBuilder(JsonTypeInfo.Value settings) { _includeAs = settings.getInclusionType(); _typeProperty = _propName(settings.getPropertyName(), _idType); _defaultImpl = settings.getDefaultImpl(); - _typeIdVisible = settings.getIdVisible(); + _typeIdVisible = settings.getIdVisible(); // was missing from Jackson 3.0 _requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes(); } } @@ -143,6 +138,9 @@ public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) return this; } + /** + * @since 2.16 (backported from Jackson 3.0) + */ @Override public StdTypeResolverBuilder init(JsonTypeInfo.Value settings, TypeIdResolver idRes) @@ -345,11 +343,6 @@ public StdTypeResolverBuilder withDefaultImpl(Class defaultImpl) { return new StdTypeResolverBuilder(this, defaultImpl); } - @Override - public void requireTypeIdForSubtypes(Boolean requireTypeId) { - _requireTypeIdForSubtypes = requireTypeId; - } - /* /********************************************************** /* Accessors From e11d5ecefedbb384fbf79fdcee878f16ff762f4e Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Sat, 27 May 2023 13:00:57 +0900 Subject: [PATCH 9/9] Clean up changes --- .../introspect/JacksonAnnotationIntrospector.java | 1 + .../databind/jsontype/impl/StdTypeResolverBuilder.java | 8 +++----- 2 files changed, 4 insertions(+), 5 deletions(-) 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 97fa30aedb..6ff5b7d08f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java +++ b/src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java @@ -1555,6 +1555,7 @@ protected TypeResolverBuilder _findTypeResolver(MapperConfig config, if (defaultImpl != null && defaultImpl != JsonTypeInfo.None.class && !defaultImpl.isAnnotation()) { typeInfo = typeInfo.withDefaultImpl(defaultImpl); } + b = b.init(typeInfo, idRes); return b; } 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 e7af475599..cfc8fb058f 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; @@ -38,7 +39,7 @@ public class StdTypeResolverBuilder /** * * Boolean value configured through {@link JsonTypeInfo#requireTypeIdForSubtypes}. - * If this value is not {@code null}, this value overrides the global configuration of + * If this value is not {@code null}, this value should override the global configuration of * {@link com.fasterxml.jackson.databind.MapperFeature#REQUIRE_TYPE_ID_FOR_SUBTYPES}. * * @since 2.16 (backported from Jackson 3.0) @@ -103,7 +104,7 @@ public StdTypeResolverBuilder(JsonTypeInfo.Value settings) { _includeAs = settings.getInclusionType(); _typeProperty = _propName(settings.getPropertyName(), _idType); _defaultImpl = settings.getDefaultImpl(); - _typeIdVisible = settings.getIdVisible(); // was missing from Jackson 3.0 + _typeIdVisible = settings.getIdVisible(); _requireTypeIdForSubtypes = settings.getRequireTypeIdForSubtypes(); } } @@ -138,9 +139,6 @@ public StdTypeResolverBuilder init(JsonTypeInfo.Id idType, TypeIdResolver idRes) return this; } - /** - * @since 2.16 (backported from Jackson 3.0) - */ @Override public StdTypeResolverBuilder init(JsonTypeInfo.Value settings, TypeIdResolver idRes)