Skip to content

Commit 79b2de3

Browse files
authored
Fix #4896: deserialize enum from "" (#4923)
1 parent 17858e9 commit 79b2de3

File tree

4 files changed

+35
-33
lines changed

4 files changed

+35
-33
lines changed

release-notes/VERSION-2.x

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,8 @@ Project: jackson-databind
4141
#4867: Add `Optional<JsonNode> JsonNode.asOptional()` convenience method
4242
(fix by Joo-Hyuk K)
4343
#4869: Add `JsonNode.values()` to replace `elements()`
44+
#4896: Coercion shouldn't be necessary for Enums specifying an empty string
45+
(reported by @joaocanaverde-blue)
4446
4547
2.18.3 (not yet released)
4648

src/main/java/com/fasterxml/jackson/databind/introspect/JacksonAnnotationIntrospector.java

Lines changed: 8 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -177,36 +177,8 @@ public boolean isAnnotationBundle(Annotation ann) {
177177
/**********************************************************
178178
*/
179179

180-
/**
181-
* Since 2.6, we have supported use of {@link JsonProperty} for specifying
182-
* explicit serialized name
183-
*/
184-
@Override
185-
@Deprecated // since 2.8
186-
public String findEnumValue(Enum<?> value)
187-
{
188-
// 11-Jun-2015, tatu: As per [databind#677], need to allow explicit naming.
189-
// Unfortunately cannot quite use standard AnnotatedClass here (due to various
190-
// reasons, including odd representation JVM uses); has to do for now
191-
try {
192-
// We know that values are actually static fields with matching name so:
193-
Field f = value.getDeclaringClass().getField(value.name());
194-
if (f != null) {
195-
JsonProperty prop = f.getAnnotation(JsonProperty.class);
196-
if (prop != null) {
197-
String n = prop.value();
198-
if (n != null && !n.isEmpty()) {
199-
return n;
200-
}
201-
}
202-
}
203-
} catch (SecurityException e) {
204-
// 17-Sep-2015, tatu: Anything we could/should do here?
205-
} catch (NoSuchFieldException e) {
206-
// 17-Sep-2015, tatu: should not really happen. But... can we do anything?
207-
}
208-
return value.name();
209-
}
180+
// @since 2.19 no longer overridden; been deprecated since 2.8
181+
//public String findEnumValue(Enum<?> value)
210182

211183
@Override // since 2.7
212184
@Deprecated // since 2.16
@@ -221,9 +193,12 @@ public String[] findEnumValues(Class<?> enumType, Enum<?>[] enumValues, String[]
221193
continue;
222194
}
223195
String n = prop.value();
196+
// 24-Jan-2025, tatu: [databind#4896] Should not skip "" with enums
197+
/*
224198
if (n.isEmpty()) {
225199
continue;
226200
}
201+
*/
227202
if (expl == null) {
228203
expl = new HashMap<String,String>();
229204
}
@@ -251,7 +226,9 @@ public String[] findEnumValues(MapperConfig<?> config, AnnotatedClass annotatedC
251226
JsonProperty property = field.getAnnotation(JsonProperty.class);
252227
if (property != null) {
253228
String propValue = property.value();
254-
if (propValue != null && !propValue.isEmpty()) {
229+
if (propValue != null) {
230+
// 24-Jan-2025, tatu: [databind#4896] Should not skip "" with enums
231+
// && !propValue.isEmpty()) {
255232
enumToPropertyMap.put(field.getName(), propValue);
256233
}
257234
}

src/main/java/com/fasterxml/jackson/databind/util/CompactStringObjectMap.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ private final static int findSize(int size)
9696
return result;
9797
}
9898

99-
public Object find(String key) {
99+
public Object find(String key)
100+
{
100101
int slot = key.hashCode() & _hashMask;
101102
int ix = (slot<<1);
102103
Object match = _hashArea[ix];

src/test/java/com/fasterxml/jackson/databind/deser/enums/EnumDeserializationTest.java

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -205,7 +205,6 @@ public Object deserializeKey(String key, DeserializationContext ctxt) throws IOE
205205
}
206206
}
207207

208-
209208
@JsonDeserialize(using = AnEnumDeserializer.class, keyUsing = AnEnumKeyDeserializer.class)
210209
public enum LanguageCodeMixin {
211210
}
@@ -279,6 +278,18 @@ public static Operation3006 forValue(final String idStr) {
279278
}
280279
}
281280

281+
// [databind#4896]
282+
enum YesOrNoOrEmpty4896 {
283+
@JsonProperty("")
284+
EMPTY,
285+
286+
@JsonProperty("yes")
287+
YES,
288+
289+
@JsonProperty("no")
290+
NO;
291+
}
292+
282293
/*
283294
/**********************************************************
284295
/* Test methods
@@ -814,4 +825,15 @@ public void testEnumFeature_READ_ENUM_KEYS_USING_INDEX_isDisabledByDefault() {
814825
.isEnabled(EnumFeature.READ_ENUM_KEYS_USING_INDEX));
815826
}
816827

828+
// [databind#4896]
829+
@Test
830+
public void testEnumReadFromEmptyString() throws Exception {
831+
// First, regular value
832+
assertEquals(YesOrNoOrEmpty4896.YES,
833+
MAPPER.readerFor(YesOrNoOrEmpty4896.class)
834+
.readValue(q("yes")));
835+
assertEquals(YesOrNoOrEmpty4896.EMPTY,
836+
MAPPER.readerFor(YesOrNoOrEmpty4896.class)
837+
.readValue(q("")));
838+
}
817839
}

0 commit comments

Comments
 (0)