Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Using JsonCreator cause generating invalid path reference in JsonMappingException #801

Merged
merged 3 commits into from
May 22, 2015
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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());
}
}
}