Skip to content

Commit

Permalink
Fix #3006
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder committed Oct 13, 2021
1 parent a6ce028 commit f875dbc
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 20 deletions.
6 changes: 6 additions & 0 deletions release-notes/VERSION-2.x
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,12 @@ Project: jackson-databind
=== Releases ===
------------------------------------------------------------------------

2.13.1 (not yet released)

#3006: Argument type mismatch for `enum` with `@JsonCreator` that takes String,
gets JSON Number
(reported by GrozaAnton@github)

2.13.0 (30-Sep-2021)

#1850: `@JsonValue` with integer for enum does not deserialize correctly
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@ class FactoryBasedEnumDeserializer
{
private static final long serialVersionUID = 1;

// Marker type; null if String expected; otherwise numeric wrapper
// Marker type; null if String expected; otherwise usually numeric wrapper
protected final JavaType _inputType;
protected final boolean _hasArgs;
protected final AnnotatedMethod _factory;
protected final JsonDeserializer<?> _deser;
protected final ValueInstantiator _valueInstantiator;
protected final SettableBeanProperty[] _creatorProps;

protected final boolean _hasArgs;

/**
* Lazily instantiated property-based creator.
*
Expand All @@ -51,7 +52,8 @@ public FactoryBasedEnumDeserializer(Class<?> cls, AnnotatedMethod f, JavaType pa
_factory = f;
_hasArgs = true;
// We'll skip case of `String`, as well as no type (zero-args):
_inputType = paramType.hasRawClass(String.class) ? null : paramType;
_inputType = (paramType.hasRawClass(String.class) || paramType.hasRawClass(CharSequence.class))
? null : paramType;
_deser = null;
_valueInstantiator = valueInstantiator;
_creatorProps = creatorProps;
Expand Down Expand Up @@ -88,6 +90,9 @@ public JsonDeserializer<?> createContextual(DeserializationContext ctxt,
BeanProperty property)
throws JsonMappingException
{
// So: no need to fetch if we had it; or if target is `String`(-like); or
// if we have properties-based Creator (for which we probably SHOULD do
// different contextualization?)
if ((_deser == null) && (_inputType != null) && (_creatorProps == null)) {
return new FactoryBasedEnumDeserializer(this,
ctxt.findContextualValueDeserializer(_inputType, property));
Expand Down Expand Up @@ -116,11 +121,14 @@ public LogicalType logicalType() {
public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException
{
Object value;

// First: the case of having deserializer for non-String input for delegating
// Creator method
if (_deser != null) {
value = _deser.deserialize(p, ctxt);
} else if (_hasArgs) {
JsonToken curr = p.currentToken();

// Second: property- and delegating-creators
} else if (_hasArgs) {
// 30-Mar-2020, tatu: For properties-based one, MUST get JSON Object (before
// 2.11, was just assuming match)
if (_creatorProps != null) {
Expand All @@ -138,15 +146,9 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
return deserializeEnumUsingPropertyBased(p, ctxt, _propCreator);
}

// 30-Mar-2020, tatu: Single-arg delegating creators may go through
// here; although not 100% sure why they do not take the first branch
if (curr == JsonToken.VALUE_STRING || curr == JsonToken.FIELD_NAME) {
value = p.getText();
} else if (curr == JsonToken.VALUE_NUMBER_INT) {
value = p.getNumberValue();
} else {
value = p.getValueAsString();
}
// 12-Oct-2021, tatu: We really should only get here if and when String
// value is expected; otherwise Deserializer should have been used earlier
value = p.getValueAsString();
} else { // zero-args; just skip whatever value there may be
p.skipChildren();
try {
Expand All @@ -160,10 +162,13 @@ public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOEx
return _factory.callOnWith(_valueClass, value);
} catch (Exception e) {
Throwable t = ClassUtil.throwRootCauseIfIOE(e);
// [databind#1642]:
if (ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL) &&
t instanceof IllegalArgumentException) {
return null;
if (t instanceof IllegalArgumentException) {
// [databind#1642]:
if (ctxt.isEnabled(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL)) {
return null;
}
// 12-Oct-2021, tatu: Should probably try to provide better exception since
// we likely hit argument incompatibility... Or can this happen?
}
return ctxt.handleInstantiationProblem(_valueClass, value, t);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,8 +134,6 @@ static enum StrictEnumCreator {
}
}

// //

public enum AnEnum {
ZERO,
ONE
Expand Down Expand Up @@ -217,6 +215,33 @@ public String toString() {
}
}

// [databind#3006]
enum Operation3006 {
ONE(1L), TWO(2L), THREE(3L);

private static final Map<Long, Operation3006> mapping = new HashMap<>();
static {
for (Operation3006 operation : Operation3006.values()) {
mapping.put(operation.id, operation);
}
}

final long id;

Operation3006(final long id) {
this.id = id;
}

@JsonCreator
public static Operation3006 forValue(final String idStr) {
Operation3006 candidate = mapping.get(Long.parseLong(idStr));
if (candidate == null) {
throw new IllegalArgumentException("Unable to find: " + idStr);
}
return candidate;
}
}

/*
/**********************************************************
/* Test methods
Expand Down Expand Up @@ -618,4 +643,13 @@ public void testAllowCaseInsensitiveEnumValues() throws Exception {
assertEquals(1, result.map.size());
assertEquals("val", result.map.get(TestEnum.JACKSON));
}

// [databind#3006]
public void testIssue3006() throws Exception
{
assertEquals(Operation3006.ONE, MAPPER.readValue("1", Operation3006.class));
assertEquals(Operation3006.ONE, MAPPER.readValue(q("1"), Operation3006.class));
assertEquals(Operation3006.THREE, MAPPER.readValue("3", Operation3006.class));
assertEquals(Operation3006.THREE, MAPPER.readValue(q("3"), Operation3006.class));
}
}

0 comments on commit f875dbc

Please sign in to comment.