9
9
import com .fasterxml .jackson .core .*;
10
10
11
11
import com .fasterxml .jackson .databind .*;
12
+ import com .fasterxml .jackson .databind .annotation .EnumNaming ;
12
13
import com .fasterxml .jackson .databind .annotation .JacksonStdImpl ;
13
14
import com .fasterxml .jackson .databind .cfg .CoercionAction ;
14
15
import com .fasterxml .jackson .databind .cfg .CoercionInputShape ;
15
16
import com .fasterxml .jackson .databind .deser .ContextualDeserializer ;
16
17
import com .fasterxml .jackson .databind .deser .SettableBeanProperty ;
17
18
import com .fasterxml .jackson .databind .deser .ValueInstantiator ;
18
19
import com .fasterxml .jackson .databind .introspect .AnnotatedMethod ;
20
+ import com .fasterxml .jackson .databind .introspect .EnumPropertiesCollector ;
19
21
import com .fasterxml .jackson .databind .type .LogicalType ;
20
22
import com .fasterxml .jackson .databind .util .ClassUtil ;
21
23
import com .fasterxml .jackson .databind .util .CompactStringObjectMap ;
@@ -66,31 +68,21 @@ public class EnumDeserializer
66
68
*/
67
69
protected final boolean _isFromIntValue ;
68
70
69
- protected Boolean _useEnumNaming ;
70
-
71
- protected volatile EnumNamingStrategy _namingStrategy ;
72
-
73
71
/**
74
- * Marker flag for cases where we expect actual integral value for Enum,
75
- * based on {@code @JsonValue} (and equivalent) annotated accessor .
72
+ * Marker flag for deciding whether to search for {@link com.fasterxml.jackson.databind.annotation.EnumNaming}
73
+ * annotation. Value starts as null to indicate verification has not been performed yet .
76
74
*
77
75
* @since 2.15
78
76
*/
79
- protected boolean _isEnumNamingSet ;
77
+ private volatile Boolean _hasEnumNaming = null ;
80
78
81
79
/**
80
+ * Map with key as converted property class defined implementation of {@link EnumNamingStrategy}
81
+ * and with value as Enum names collected using <code>Enum.name()</code>.
82
+ *
82
83
* @since 2.15
83
84
*/
84
- protected EnumNamingStrategy _namingStrategy = new EnumNamingStrategies .NoOpEnumNamingStrategy ();
85
-
86
-
87
- private void _initEnumNamingStrategy () {
88
- EnumNaming enumNamingAnnotation = _valueClass .getAnnotation (EnumNaming .class );
89
- if (enumNamingAnnotation != null ) {
90
- _isEnumNamingSet = true ;
91
- ClassUtil .createInstance (enumNamingAnnotation .value (), true );
92
- }
93
- }
85
+ protected volatile CompactStringObjectMap _lookupByEnumNaming ;
94
86
95
87
/**
96
88
* @since 2.9
@@ -103,7 +95,6 @@ public EnumDeserializer(EnumResolver byNameResolver, Boolean caseInsensitive)
103
95
_enumDefaultValue = byNameResolver .getDefaultValue ();
104
96
_caseInsensitive = caseInsensitive ;
105
97
_isFromIntValue = byNameResolver .isFromIntValue ();
106
- _initEnumNamingStrategy ();
107
98
}
108
99
109
100
/**
@@ -120,7 +111,6 @@ protected EnumDeserializer(EnumDeserializer base, Boolean caseInsensitive,
120
111
_isFromIntValue = base ._isFromIntValue ;
121
112
_useDefaultValueForUnknownEnum = useDefaultValueForUnknownEnum ;
122
113
_useNullForUnknownEnum = useNullForUnknownEnum ;
123
- _initEnumNamingStrategy ();
124
114
}
125
115
126
116
/**
@@ -282,13 +272,9 @@ protected Object _fromString(JsonParser p, DeserializationContext ctxt,
282
272
{
283
273
CompactStringObjectMap lookup = ctxt .isEnabled (DeserializationFeature .READ_ENUMS_USING_TO_STRING )
284
274
? _getToStringLookup (ctxt ) : _lookupByName ;
285
- Object result = lookup .find (text );
286
-
287
- if (result == null && _getUseEnumNaming ()) {
288
- String translatedText = _getNamingStrategy ().translate (text );
289
- result = lookup .find (translatedText );
290
- }
275
+ lookup = _hasEnumNaming (ctxt ) ? _getEnumNamingLookup (ctxt ) : lookup ;
291
276
277
+ Object result = lookup .find (text );
292
278
if (result == null ) {
293
279
String trimmed = text .trim ();
294
280
if ((trimmed == text ) || (result = lookup .find (trimmed )) == null ) {
@@ -352,12 +338,6 @@ private final Object _deserializeAltString(JsonParser p, DeserializationContext
352
338
CompactStringObjectMap lookup , String nameOrig ) throws IOException
353
339
{
354
340
String name = nameOrig .trim ();
355
-
356
- if (_isEnumNamingSet ) {
357
- String translatedValue = _namingStrategy .translate (name );
358
- return lookup .find (translatedValue );
359
- }
360
-
361
341
if (name .isEmpty ()) { // empty or blank
362
342
// 07-Jun-2021, tatu: [databind#3171] Need to consider Default value first
363
343
// (alas there's bit of duplication here)
@@ -454,30 +434,6 @@ protected CompactStringObjectMap _getToStringLookup(DeserializationContext ctxt)
454
434
return lookup ;
455
435
}
456
436
457
- protected Boolean _getUseEnumNaming () {
458
- if (_useEnumNaming == null ) {
459
- _useEnumNaming = _valueClass .getAnnotation (EnumNaming .class ) != null ;
460
- }
461
- return _useEnumNaming ;
462
- }
463
-
464
- protected EnumNamingStrategy _getNamingStrategy () {
465
- EnumNamingStrategy namingStrategy = _namingStrategy ;
466
- if (namingStrategy == null ) {
467
- synchronized (this ) {
468
- namingStrategy = _namingStrategy ;
469
- if (namingStrategy == null ) {
470
- EnumNaming enumNamingAnnotation = _valueClass .getAnnotation (EnumNaming .class );
471
- namingStrategy = enumNamingAnnotation == null
472
- ? new EnumNamingStrategies .NoOpEnumNamingStrategy ()
473
- : ClassUtil .createInstance (enumNamingAnnotation .value (), true );
474
- _namingStrategy = namingStrategy ;
475
- }
476
- }
477
- }
478
- return namingStrategy ;
479
- }
480
-
481
437
// @since 2.15
482
438
protected boolean useNullForUnknownEnum (DeserializationContext ctxt ) {
483
439
return Boolean .TRUE .equals (_useNullForUnknownEnum )
@@ -490,4 +446,49 @@ protected boolean useDefaultValueForUnknownEnum(DeserializationContext ctxt) {
490
446
&& (Boolean .TRUE .equals (_useDefaultValueForUnknownEnum )
491
447
|| ctxt .isEnabled (DeserializationFeature .READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE ));
492
448
}
449
+
450
+ /**
451
+ * Checks wheather current Enum class is annotated with
452
+ * {@link com.fasterxml.jackson.databind.annotation.EnumNaming}
453
+ *
454
+ * @since 2.15
455
+ */
456
+ private boolean _hasEnumNaming (DeserializationContext ctxt ) {
457
+ Boolean exists = _hasEnumNaming ;
458
+ if (exists == null ) {
459
+ synchronized (this ) {
460
+ exists = _hasEnumNaming ;
461
+ if (exists == null ) {
462
+ exists = _getEnumNamingLookup (ctxt ) != null ;
463
+ _hasEnumNaming = exists ;
464
+ }
465
+ }
466
+ }
467
+ return exists ;
468
+ }
469
+
470
+ /**
471
+ * Returns the CompactStringObjectMap used for enum name lookup of naming strategy.
472
+ *
473
+ * @since 2.15
474
+ */
475
+ protected CompactStringObjectMap _getEnumNamingLookup (DeserializationContext ctxt ) {
476
+ CompactStringObjectMap lookup = _lookupByEnumNaming ;
477
+ if (lookup == null ) {
478
+ synchronized (this ) {
479
+ lookup = _lookupByEnumNaming ;
480
+ if (lookup == null ) {
481
+ EnumNamingStrategy namingStrategy = EnumPropertiesCollector
482
+ .findEnumNamingStrategy (ctxt .getConfig (), _valueClass );
483
+ if (namingStrategy != null ) {
484
+ lookup = EnumResolver
485
+ .constructUsingEnumNamingStrategy (ctxt .getConfig (), _enumClass (), namingStrategy )
486
+ .constructLookup ();
487
+ _lookupByEnumNaming = lookup ;
488
+ }
489
+ }
490
+ }
491
+ }
492
+ return lookup ;
493
+ }
493
494
}
0 commit comments