From e90b1c4be87fb99ea8ffaf1197e05a891833f2c0 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 13 Jul 2023 00:29:40 +0900 Subject: [PATCH 1/5] Retrofit byIndexResolver of Enum --- .../deser/BasicDeserializerFactory.java | 7 +++-- .../deser/std/StdKeyDeserializer.java | 13 +++++++-- .../deser/std/StdKeyDeserializers.java | 11 ++++--- .../jackson/databind/util/EnumResolver.java | 29 +++++++++++++++++++ 4 files changed, 52 insertions(+), 8 deletions(-) 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 a031ed4da9..b54bbe2502 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -1925,6 +1925,7 @@ private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, EnumResolver enumRes = constructEnumResolver(enumClass, config, beanDesc); EnumResolver byEnumNamingResolver = constructEnumNamingStrategyResolver(config, enumClass, beanDesc.getClassInfo()); EnumResolver byToStringResolver = EnumResolver.constructUsingToString(config, beanDesc.getClassInfo()); + EnumResolver byIndexResolver = EnumResolver.constructUsingIndex(config, beanDesc.getClassInfo()); // May have @JsonCreator for static factory method for (AnnotatedMethod factory : beanDesc.getFactoryMethods()) { @@ -1946,7 +1947,8 @@ private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, ClassUtil.checkAndFixAccess(factory.getMember(), ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } - return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory, byEnumNamingResolver, byToStringResolver); + return StdKeyDeserializers.constructEnumKeyDeserializer( + enumRes, factory, byEnumNamingResolver, byToStringResolver, byIndexResolver); } } throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type " @@ -1954,7 +1956,8 @@ private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, } } // Also, need to consider @JsonValue, if one found - return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, byEnumNamingResolver, byToStringResolver); + return StdKeyDeserializers.constructEnumKeyDeserializer( + enumRes, byEnumNamingResolver, byToStringResolver, byIndexResolver); } /* diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java index e69269ac81..5729e6ced9 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializer.java @@ -406,13 +406,14 @@ protected EnumKD(EnumResolver er, AnnotatedMethod factory) { * @since 2.16 */ protected EnumKD(EnumResolver er, AnnotatedMethod factory, EnumResolver byEnumNamingResolver, - EnumResolver byToStringResolver) { + EnumResolver byToStringResolver, EnumResolver byIndexResolver) { super(-1, er.getEnumClass()); _byNameResolver = er; _factory = factory; _enumDefaultValue = er.getDefaultValue(); _byEnumNamingResolver = byEnumNamingResolver; _byToStringResolver = byToStringResolver; + _byIndexResolver = byIndexResolver; } @@ -461,7 +462,7 @@ protected EnumResolver _resolveCurrentResolver(DeserializationContext ctxt) { /** * Since 2.16, {@link #_byToStringResolver} it is passed via - * {@link #EnumKD(EnumResolver, AnnotatedMethod, EnumResolver, EnumResolver)}, so there is no need for lazy + * {@link #EnumKD(EnumResolver, AnnotatedMethod, EnumResolver, EnumResolver, EnumResolver)}, so there is no need for lazy * initialization. But kept for backward-compatilibility reasons. * * @deprecated Since 2.16 @@ -483,6 +484,14 @@ private EnumResolver _getToStringResolver(DeserializationContext ctxt) return res; } + /** + * Since 2.16, {@link #_byIndexResolver} it is passed via + * {@link #EnumKD(EnumResolver, AnnotatedMethod, EnumResolver, EnumResolver, EnumResolver)}, so there is no need for lazy + * initialization. But kept for backward-compatilibility reasons. + * + * @deprecated Since 2.16 + */ + @Deprecated private EnumResolver _getIndexResolver(DeserializationContext ctxt) { EnumResolver res = _byIndexResolver; if (res == null) { diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java index 1914ab9896..daff869bf8 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java @@ -47,16 +47,19 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumReso /** * @since 2.16 */ - public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, EnumResolver byToStringResolver) { - return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver); + public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, + EnumResolver byToStringResolver, EnumResolver byIndexResolver) { + return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver, + byIndexResolver); } /** * @since 2.16 */ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumResolver, AnnotatedMethod factory, - EnumResolver enumNamingResolver, EnumResolver byToStringResolver) { - return new StdKeyDeserializer.EnumKD(enumResolver, factory, enumNamingResolver, byToStringResolver); + EnumResolver enumNamingResolver, EnumResolver byToStringResolver, EnumResolver byIndexResolver) { + return new StdKeyDeserializer.EnumKD(enumResolver, factory, enumNamingResolver, byToStringResolver, + byIndexResolver); } public static KeyDeserializer constructDelegatingKeyDeserializer(DeserializationConfig config, diff --git a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java index 0569fef860..38d4b63586 100644 --- a/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java +++ b/src/main/java/com/fasterxml/jackson/databind/util/EnumResolver.java @@ -239,7 +239,9 @@ public static EnumResolver constructUsingToString(DeserializationConfig config, * Enum value * * @since 2.15 + * @deprecated Since 2.16. Use {@link #constructUsingIndex(DeserializationConfig, AnnotatedClass)} instead. */ + @Deprecated public static EnumResolver constructUsingIndex(DeserializationConfig config, Class> enumCls0) { @@ -258,6 +260,33 @@ public static EnumResolver constructUsingIndex(DeserializationConfig config, _enumDefault(ai, enumCls), isIgnoreCase, false); } + /** + * Factory method for constructing resolver that maps from index of Enum.values() into + * Enum value. + * + * @since 2.16 + */ + public static EnumResolver constructUsingIndex(DeserializationConfig config, AnnotatedClass annotatedClass) + { + // prepare data + final AnnotationIntrospector ai = config.getAnnotationIntrospector(); + final boolean isIgnoreCase = config.isEnabled(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS); + final Class enumCls0 = annotatedClass.getRawType(); + final Class> enumCls = _enumClass(enumCls0); + final Enum[] enumConstants = _enumConstants(enumCls0); + final Enum defaultEnum = _enumDefault(ai, annotatedClass, enumConstants); + + // finally, build + // from last to first, so that in case of duplicate values, first wins + HashMap> map = new HashMap<>(); + for (int i = enumConstants.length; --i >= 0; ) { + Enum enumValue = enumConstants[i]; + map.put(String.valueOf(i), enumValue); + } + return new EnumResolver(enumCls, enumConstants, map, + defaultEnum, isIgnoreCase, false); + } + /** * Factory method for constructing resolver that maps the name of enums converted to external property * names into Enum value using an implementation of {@link EnumNamingStrategy}. From 34b06cd6bfd35520f3daa28dfc1090315a6970f5 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 13 Jul 2023 07:58:28 +0900 Subject: [PATCH 2/5] Improve construction readability in EnumKD by reformat --- .../jackson/databind/deser/std/StdKeyDeserializers.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java index daff869bf8..5e2428ebae 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java @@ -49,8 +49,7 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumReso */ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, EnumResolver byToStringResolver, EnumResolver byIndexResolver) { - return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver, - byIndexResolver); + return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver, byIndexResolver); } /** @@ -58,8 +57,7 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, */ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumResolver, AnnotatedMethod factory, EnumResolver enumNamingResolver, EnumResolver byToStringResolver, EnumResolver byIndexResolver) { - return new StdKeyDeserializer.EnumKD(enumResolver, factory, enumNamingResolver, byToStringResolver, - byIndexResolver); + return new StdKeyDeserializer.EnumKD(enumResolver, factory, enumNamingResolver, byToStringResolver, byIndexResolver); } public static KeyDeserializer constructDelegatingKeyDeserializer(DeserializationConfig config, From 6fdeeea2f769a335337dd7fc9b9c688a63da48a6 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 13 Jul 2023 08:03:34 +0900 Subject: [PATCH 3/5] Format constructEnumKeyDeserializer() --- .../jackson/databind/deser/std/StdKeyDeserializers.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java index 5e2428ebae..52cac74b2c 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java @@ -48,7 +48,8 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumReso * @since 2.16 */ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, - EnumResolver byToStringResolver, EnumResolver byIndexResolver) { + EnumResolver byToStringResolver, EnumResolver byIndexResolver) + { return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver, byIndexResolver); } @@ -56,7 +57,8 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, * @since 2.16 */ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumResolver, AnnotatedMethod factory, - EnumResolver enumNamingResolver, EnumResolver byToStringResolver, EnumResolver byIndexResolver) { + EnumResolver enumNamingResolver, EnumResolver byToStringResolver, EnumResolver byIndexResolver) + { return new StdKeyDeserializer.EnumKD(enumResolver, factory, enumNamingResolver, byToStringResolver, byIndexResolver); } From 989dc0c530247d9d11b0c86222779d50a3f31400 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 13 Jul 2023 08:04:55 +0900 Subject: [PATCH 4/5] Update BasicDeserializerFactory.java --- .../jackson/databind/deser/BasicDeserializerFactory.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) 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 b54bbe2502..1d79d5df3f 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BasicDeserializerFactory.java @@ -1947,8 +1947,7 @@ private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, ClassUtil.checkAndFixAccess(factory.getMember(), ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS)); } - return StdKeyDeserializers.constructEnumKeyDeserializer( - enumRes, factory, byEnumNamingResolver, byToStringResolver, byIndexResolver); + return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, factory, byEnumNamingResolver, byToStringResolver, byIndexResolver); } } throw new IllegalArgumentException("Unsuitable method ("+factory+") decorated with @JsonCreator (for Enum type " @@ -1956,8 +1955,7 @@ private KeyDeserializer _createEnumKeyDeserializer(DeserializationContext ctxt, } } // Also, need to consider @JsonValue, if one found - return StdKeyDeserializers.constructEnumKeyDeserializer( - enumRes, byEnumNamingResolver, byToStringResolver, byIndexResolver); + return StdKeyDeserializers.constructEnumKeyDeserializer(enumRes, byEnumNamingResolver, byToStringResolver, byIndexResolver); } /* From 69aa779f34e9f5130f8c17148ed2b80a7e4c2ff5 Mon Sep 17 00:00:00 2001 From: joohyukkim Date: Thu, 13 Jul 2023 08:07:49 +0900 Subject: [PATCH 5/5] Update StdKeyDeserializers.java --- .../jackson/databind/deser/std/StdKeyDeserializers.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java index 52cac74b2c..12159de205 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/std/StdKeyDeserializers.java @@ -47,8 +47,8 @@ public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumReso /** * @since 2.16 */ - public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, - EnumResolver byToStringResolver, EnumResolver byIndexResolver) + public static KeyDeserializer constructEnumKeyDeserializer(EnumResolver enumRes, EnumResolver byEnumNamingResolver, EnumResolver byToStringResolver, + EnumResolver byIndexResolver) { return new StdKeyDeserializer.EnumKD(enumRes, null, byEnumNamingResolver, byToStringResolver, byIndexResolver); }