Fixed [JACKSON-377], ThrowableDeserializer not correctly handling @JsonCreator or @JsonAnySetter
diff --git a/release-notes/CREDITS b/release-notes/CREDITS
index 4ae05ab..592e477 100644
--- a/release-notes/CREDITS
+++ b/release-notes/CREDITS
@@ -400,6 +400,9 @@
* Suggested [JACKSON-308] Configurable date formatting support for XMLGregorianCalendar,
XMLGregorianCalendar now uses same Date/Calendar serialization as other date types.
[1.6.0]
-
-
+
+Kirill Stokoz:
+ * Reported [JACKSON-377] ThrowableDeserializer was not properly using information from
+ @JsonCreator or @JsonAnySetter
+ [1.6.1]
\ No newline at end of file
diff --git a/release-notes/VERSION b/release-notes/VERSION
index d263ff1..fa0bd76 100644
--- a/release-notes/VERSION
+++ b/release-notes/VERSION
@@ -10,7 +10,10 @@
* [JACKSON-372] handle missing primitive type values for @JsonCreator gracefully (with defaults)
* [JACKSON-376] writing binary data as object field value with Smile failed
- (report by Shay B)
+ (reported by Shay B)
+ * [JACKSON-377] ThrowableDeserializer was not properly using information from
+ @JsonCreator or @JsonAnySetter
+ (reported by Kirill S)
* all fixes from 1.5.x up to 1.5.7
------------------------------------------------------------------------
diff --git a/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java b/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java
index e27d0ca..507866e 100644
--- a/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java
+++ b/src/mapper/java/org/codehaus/jackson/map/deser/ThrowableDeserializer.java
@@ -13,12 +13,12 @@
public class ThrowableDeserializer
extends BeanDeserializer
{
- final static String PROP_NAME_MESSAGE = "message";
+ protected final static String PROP_NAME_MESSAGE = "message";
/*
- ///////////////////////////////////////////////////////
- // Construction
- ///////////////////////////////////////////////////////
+ /**********************************************************
+ /* Construction
+ /**********************************************************
*/
public ThrowableDeserializer(JavaType type)
@@ -27,15 +27,32 @@
}
/*
- ///////////////////////////////////////////////////////
- // Overridden methods
- ///////////////////////////////////////////////////////
+ /**********************************************************
+ /* Overridden methods
+ /**********************************************************
*/
@Override
public Object deserializeFromObject(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException
{
+ // 30-Sep-2010, tatu: Need to allow use of @JsonCreator, so:
+ if (_propertyBasedCreator != null) { // proper @JsonCreator
+ return _deserializeUsingPropertyBased(jp, ctxt);
+ }
+ if (_delegatingCreator != null) { // delegate based one (single-arg, no property name)
+ return _delegatingCreator.deserialize(jp, ctxt);
+ }
+ if (_beanType.isAbstract()) { // for good measure, check this too
+ throw JsonMappingException.from(jp, "Can not instantiate abstract type "+_beanType
+ +" (need to add/enable type information?)");
+ }
+ // and finally, verify we do have single-String arg constructor (if no @JsonCreator)
+ if (_stringCreator == null) {
+ throw new JsonMappingException("Can not deserialize Throwable of type "+_beanType
+ +" without having either single-String-arg constructor; or explicit @JsonCreator");
+ }
+
Object throwable = null;
Object[] pending = null;
int pendingIx = 0;
@@ -73,6 +90,17 @@
}
continue;
}
+ /* As per [JACKSON-313], things marked as ignorable should not be
+ * passed to any setter
+ */
+ if (_ignorableProps != null && _ignorableProps.contains(propName)) {
+ jp.skipChildren();
+ continue;
+ }
+ if (_anySetter != null) {
+ _anySetter.deserializeAndSet(jp, ctxt, throwable, propName);
+ continue;
+ }
// Unknown: let's call handler method
handleUnknownProperty(jp, ctxt, throwable, propName);
}
diff --git a/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java b/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java
index 4b69433..527c4a2 100644
--- a/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java
+++ b/src/test/org/codehaus/jackson/map/deser/TestExceptionDeserialization.java
@@ -3,7 +3,11 @@
import org.codehaus.jackson.map.BaseMapTest;
import java.io.IOException;
+import java.util.*;
+import org.codehaus.jackson.annotate.JsonAnySetter;
+import org.codehaus.jackson.annotate.JsonCreator;
+import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.map.*;
/**
@@ -12,8 +16,39 @@
public class TestExceptionDeserialization
extends BaseMapTest
{
- public void testIOException()
- throws IOException
+ @SuppressWarnings("serial")
+ static class MyException extends Exception
+ {
+ protected int value;
+
+ protected String myMessage;
+ protected HashMap<String,Object> stuff = new HashMap<String, Object>();
+
+ @JsonCreator
+ MyException(@JsonProperty("message") String msg, @JsonProperty("value") int v)
+ {
+ super(msg);
+ myMessage = msg;
+ value = v;
+ }
+
+ public int getValue() { return value; }
+
+ public String getFoo() { return "bar"; }
+
+ @JsonAnySetter public void setter(String key, Object value)
+ {
+ stuff.put(key, value);
+ }
+ }
+
+ /*
+ /**********************************************************
+ /* Tests
+ /**********************************************************
+ */
+
+ public void testIOException() throws IOException
{
ObjectMapper mapper = new ObjectMapper();
IOException ioe = new IOException("TEST");
@@ -24,4 +59,18 @@
assertEquals(ioe.getMessage(), result.getMessage());
}
+
+ // As per [JACKSON-377]
+ public void testWithCreator() throws IOException
+ {
+ final String MSG = "the message";
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(new MyException(MSG, 3));
+
+ MyException result = mapper.readValue(json, MyException.class);
+ assertEquals(MSG, result.getMessage());
+ assertEquals(3, result.value);
+ assertEquals(1, result.stuff.size());
+ assertEquals(result.getFoo(), result.stuff.get("foo"));
+ }
}