Skip to content

Commit

Permalink
Merge pull request #801 from Kamil-Benedykcinski/2.5
Browse files Browse the repository at this point in the history
Using JsonCreator cause generating invalid path reference in JsonMappingException
  • Loading branch information
cowtowncoder committed May 22, 2015
2 parents e412926 + 0e8d641 commit 5f09320
Show file tree
Hide file tree
Showing 3 changed files with 158 additions and 14 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
Expand All @@ -80,7 +80,7 @@ public BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir) {
public BeanDeserializer(BeanDeserializerBase src, HashSet<String> ignorableProps) {
super(src, ignorableProps);
}

@Override
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
{
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
*/
Expand All @@ -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;

Expand All @@ -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;
Expand Down Expand Up @@ -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 {
Expand All @@ -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
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -691,7 +703,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri
/* external type id
/**********************************************************
*/

protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
throws IOException
{
Expand All @@ -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();
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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());
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
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());
}
}
}

0 comments on commit 5f09320

Please sign in to comment.