From a3249d73d0a7d8f111241728eb7b756ef3b5659e Mon Sep 17 00:00:00 2001 From: Kamil Benedykcinski Date: Wed, 20 May 2015 22:06:35 +0200 Subject: [PATCH 1/3] Using JsonCreator cause generating invalid path reference in JsonMappingException --- .../databind/deser/BeanDeserializer.java | 40 +++++++---- ...ionHandlingWithDefaultDeserialization.java | 65 +++++++++++++++++ ...andlingWithJsonCreatorDeserialization.java | 71 +++++++++++++++++++ 3 files changed, 162 insertions(+), 14 deletions(-) create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java create mode 100644 src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java diff --git a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java index 5e60cb5778..c0ec22e619 100644 --- a/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java +++ b/src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java @@ -68,7 +68,7 @@ protected BeanDeserializer(BeanDeserializerBase src) { protected BeanDeserializer(BeanDeserializerBase src, boolean ignoreAllUnknown) { super(src, ignoreAllUnknown); } - + protected BeanDeserializer(BeanDeserializerBase src, NameTransformer unwrapper) { super(src, unwrapper); } @@ -80,7 +80,7 @@ public BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir) { public BeanDeserializer(BeanDeserializerBase src, HashSet ignorableProps) { super(src, ignorableProps); } - + @Override public JsonDeserializer unwrappingDeserializer(NameTransformer unwrapper) { @@ -182,7 +182,7 @@ protected Object _missingToken(JsonParser p, DeserializationContext ctxt) { throw ctxt.endOfInputException(handledType()); } - + /** * Secondary deserialization method, called in cases where POJO * instance is created as part of deserialization, potentially @@ -355,7 +355,7 @@ public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) t * Method called to deserialize bean using "property-based creator": * this means that a non-default constructor or factory method is * called, and then possibly other setters. The trick is that - * values for creator method need to be buffered, first; and + * values for creator method need to be buffered, first; and * due to non-guaranteed ordering possibly some other properties * as well. */ @@ -366,7 +366,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri { final PropertyBasedCreator creator = _propertyBasedCreator; PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader); - + // 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases TokenBuffer unknown = null; @@ -378,7 +378,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? - Object value = creatorProp.deserialize(p, ctxt); + Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName); if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) { p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; @@ -434,7 +434,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri unknown.writeFieldName(propName); unknown.copyCurrentStructure(p); } - + // We hit END_OBJECT, so: Object bean; try { @@ -454,12 +454,24 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri return bean; } + protected Object deserializeWithErrorWrapping(SettableBeanProperty creatorProp, JsonParser p, DeserializationContext ctxt, + String propName) + throws IOException { + try { + return creatorProp.deserialize(p, ctxt); + } catch (IOException e) { + wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt); + // exception below will be throw only if someone overwrite default implementation of wrapAndThrow method + throw e; + } + } + /* /********************************************************** /* Deserializing when we have to consider an active View /********************************************************** */ - + protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt, Object bean, Class activeView) throws IOException @@ -620,7 +632,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri SettableBeanProperty creatorProp = creator.findCreatorProperty(propName); if (creatorProp != null) { // Last creator property to set? - Object value = creatorProp.deserialize(p, ctxt); + Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName); if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; @@ -691,7 +703,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri /* external type id /********************************************************** */ - + protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt) throws IOException { @@ -700,14 +712,14 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont } return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt)); } - + protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt, Object bean) throws IOException { final Class activeView = _needViewProcesing ? ctxt.getActiveView() : null; final ExternalTypeHandler ext = _externalTypeIdHandler.start(); - + for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) { String propName = p.getCurrentName(); t = p.nextToken(); @@ -747,7 +759,7 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont continue; } // Unknown: let's call handler method - handleUnknownProperty(p, ctxt, bean, propName); + handleUnknownProperty(p, ctxt, bean, propName); } // and when we get this far, let's try finalizing the deal: return ext.complete(p, ctxt, bean); @@ -776,7 +788,7 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D ; } else { // Last creator property to set? - Object value = creatorProp.deserialize(p, ctxt); + Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName); if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) { t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT Object bean; diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java new file mode 100644 index 0000000000..4309a8b1bf --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java @@ -0,0 +1,65 @@ +package com.fasterxml.jackson.databind.deser; + +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; + +public class TestExceptionHandlingWithDefaultDeserialization extends BaseMapTest { + + static class Foo { + + private Bar bar; + + public Foo() { + } + + public Bar getBar() { + return bar; + } + } + + static class Bar { + + private Baz baz; + + public Bar() { + } + + public Baz getBaz() { + return baz; + } + + } + + + static class Baz { + + private String qux; + + public Baz() { + } + + public String getQux() { + return qux; + } + + } + + public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException { + // given + ObjectMapper mapper = new ObjectMapper(); + String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}"; + + // when + try { + mapper.readValue(input, Foo.class); + fail("Upsss! Exception has not been thrown."); + } catch (JsonMappingException ex) { + // then + assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]", + ex.getPathReference()); + } + } +} diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java new file mode 100644 index 0000000000..bb1a5a6eb2 --- /dev/null +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java @@ -0,0 +1,71 @@ +package com.fasterxml.jackson.databind.deser; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.databind.BaseMapTest; +import com.fasterxml.jackson.databind.JsonMappingException; +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.io.IOException; + +public class TestExceptionHandlingWithJsonCreatorDeserialization extends BaseMapTest { + + static class Foo { + + private Bar bar; + + @JsonCreator + public Foo(@JsonProperty("bar") Bar bar) { + this.bar = bar; + } + + public Bar getBar() { + return bar; + } + } + + static class Bar { + + private Baz baz; + + @JsonCreator + public Bar(@JsonProperty("baz") Baz baz) { + this.baz = baz; + } + + public Baz getBaz() { + return baz; + } + } + + + static class Baz { + + private String qux; + + @JsonCreator + public Baz(@JsonProperty("qux") String qux) { + this.qux = qux; + } + + public String getQux() { + return qux; + } + } + + public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException { + // given + ObjectMapper mapper = new ObjectMapper(); + String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}"; + + // when + try { + mapper.readValue(input, Foo.class); + fail("Upsss! Exception has not been thrown."); + } catch (JsonMappingException ex) { + // then + assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]", + ex.getPathReference()); + } + } +} From 4773b8915362ce2af8ce85543f303c7e95a2208d Mon Sep 17 00:00:00 2001 From: Kamil Benedykcinski Date: Wed, 20 May 2015 22:19:02 +0200 Subject: [PATCH 2/3] Using JsonCreator cause generating invalid path reference in JsonMappingException --- .../deser/TestExceptionHandlingWithDefaultDeserialization.java | 1 - .../TestExceptionHandlingWithJsonCreatorDeserialization.java | 1 - 2 files changed, 2 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java index 4309a8b1bf..798dc41f0f 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java @@ -33,7 +33,6 @@ public Baz getBaz() { } - static class Baz { private String qux; diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java index bb1a5a6eb2..38ea4296e9 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithJsonCreatorDeserialization.java @@ -38,7 +38,6 @@ public Baz getBaz() { } } - static class Baz { private String qux; From 0e8d6417f9544b7a980d589b043966e39413ed53 Mon Sep 17 00:00:00 2001 From: Kamil Benedykcinski Date: Wed, 20 May 2015 22:21:59 +0200 Subject: [PATCH 3/3] Using JsonCreator cause generating invalid path reference in JsonMappingException --- .../deser/TestExceptionHandlingWithDefaultDeserialization.java | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java index 798dc41f0f..1a75d94d77 100644 --- a/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java +++ b/src/test/java/com/fasterxml/jackson/databind/deser/TestExceptionHandlingWithDefaultDeserialization.java @@ -30,7 +30,6 @@ public Bar() { public Baz getBaz() { return baz; } - } static class Baz { @@ -43,7 +42,6 @@ public Baz() { public String getQux() { return qux; } - } public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException {