Skip to content

Commit 5f09320

Browse files
committed
Merge pull request #801 from Kamil-Benedykcinski/2.5
Using JsonCreator cause generating invalid path reference in JsonMappingException
2 parents e412926 + 0e8d641 commit 5f09320

File tree

3 files changed

+158
-14
lines changed

3 files changed

+158
-14
lines changed

src/main/java/com/fasterxml/jackson/databind/deser/BeanDeserializer.java

+26-14
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ protected BeanDeserializer(BeanDeserializerBase src) {
6868
protected BeanDeserializer(BeanDeserializerBase src, boolean ignoreAllUnknown) {
6969
super(src, ignoreAllUnknown);
7070
}
71-
71+
7272
protected BeanDeserializer(BeanDeserializerBase src, NameTransformer unwrapper) {
7373
super(src, unwrapper);
7474
}
@@ -80,7 +80,7 @@ public BeanDeserializer(BeanDeserializerBase src, ObjectIdReader oir) {
8080
public BeanDeserializer(BeanDeserializerBase src, HashSet<String> ignorableProps) {
8181
super(src, ignorableProps);
8282
}
83-
83+
8484
@Override
8585
public JsonDeserializer<Object> unwrappingDeserializer(NameTransformer unwrapper)
8686
{
@@ -182,7 +182,7 @@ protected Object _missingToken(JsonParser p, DeserializationContext ctxt)
182182
{
183183
throw ctxt.endOfInputException(handledType());
184184
}
185-
185+
186186
/**
187187
* Secondary deserialization method, called in cases where POJO
188188
* instance is created as part of deserialization, potentially
@@ -355,7 +355,7 @@ public Object deserializeFromObject(JsonParser p, DeserializationContext ctxt) t
355355
* Method called to deserialize bean using "property-based creator":
356356
* this means that a non-default constructor or factory method is
357357
* called, and then possibly other setters. The trick is that
358-
* values for creator method need to be buffered, first; and
358+
* values for creator method need to be buffered, first; and
359359
* due to non-guaranteed ordering possibly some other properties
360360
* as well.
361361
*/
@@ -366,7 +366,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
366366
{
367367
final PropertyBasedCreator creator = _propertyBasedCreator;
368368
PropertyValueBuffer buffer = creator.startBuilding(p, ctxt, _objectIdReader);
369-
369+
370370
// 04-Jan-2010, tatu: May need to collect unknown properties for polymorphic cases
371371
TokenBuffer unknown = null;
372372

@@ -378,7 +378,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
378378
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
379379
if (creatorProp != null) {
380380
// Last creator property to set?
381-
Object value = creatorProp.deserialize(p, ctxt);
381+
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
382382
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
383383
p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
384384
Object bean;
@@ -434,7 +434,7 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
434434
unknown.writeFieldName(propName);
435435
unknown.copyCurrentStructure(p);
436436
}
437-
437+
438438
// We hit END_OBJECT, so:
439439
Object bean;
440440
try {
@@ -454,12 +454,24 @@ protected Object _deserializeUsingPropertyBased(final JsonParser p, final Deseri
454454
return bean;
455455
}
456456

457+
protected Object deserializeWithErrorWrapping(SettableBeanProperty creatorProp, JsonParser p, DeserializationContext ctxt,
458+
String propName)
459+
throws IOException {
460+
try {
461+
return creatorProp.deserialize(p, ctxt);
462+
} catch (IOException e) {
463+
wrapAndThrow(e, _beanType.getRawClass(), propName, ctxt);
464+
// exception below will be throw only if someone overwrite default implementation of wrapAndThrow method
465+
throw e;
466+
}
467+
}
468+
457469
/*
458470
/**********************************************************
459471
/* Deserializing when we have to consider an active View
460472
/**********************************************************
461473
*/
462-
474+
463475
protected final Object deserializeWithView(JsonParser p, DeserializationContext ctxt,
464476
Object bean, Class<?> activeView)
465477
throws IOException
@@ -620,7 +632,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri
620632
SettableBeanProperty creatorProp = creator.findCreatorProperty(propName);
621633
if (creatorProp != null) {
622634
// Last creator property to set?
623-
Object value = creatorProp.deserialize(p, ctxt);
635+
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
624636
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
625637
t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
626638
Object bean;
@@ -691,7 +703,7 @@ protected Object deserializeUsingPropertyBasedWithUnwrapped(JsonParser p, Deseri
691703
/* external type id
692704
/**********************************************************
693705
*/
694-
706+
695707
protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt)
696708
throws IOException
697709
{
@@ -700,14 +712,14 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont
700712
}
701713
return deserializeWithExternalTypeId(p, ctxt, _valueInstantiator.createUsingDefault(ctxt));
702714
}
703-
715+
704716
protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationContext ctxt,
705717
Object bean)
706718
throws IOException
707719
{
708720
final Class<?> activeView = _needViewProcesing ? ctxt.getActiveView() : null;
709721
final ExternalTypeHandler ext = _externalTypeIdHandler.start();
710-
722+
711723
for (JsonToken t = p.getCurrentToken(); t == JsonToken.FIELD_NAME; t = p.nextToken()) {
712724
String propName = p.getCurrentName();
713725
t = p.nextToken();
@@ -747,7 +759,7 @@ protected Object deserializeWithExternalTypeId(JsonParser p, DeserializationCont
747759
continue;
748760
}
749761
// Unknown: let's call handler method
750-
handleUnknownProperty(p, ctxt, bean, propName);
762+
handleUnknownProperty(p, ctxt, bean, propName);
751763
}
752764
// and when we get this far, let's try finalizing the deal:
753765
return ext.complete(p, ctxt, bean);
@@ -776,7 +788,7 @@ protected Object deserializeUsingPropertyBasedWithExternalTypeId(JsonParser p, D
776788
;
777789
} else {
778790
// Last creator property to set?
779-
Object value = creatorProp.deserialize(p, ctxt);
791+
Object value = deserializeWithErrorWrapping(creatorProp, p, ctxt, propName);
780792
if (buffer.assignParameter(creatorProp.getCreatorIndex(), value)) {
781793
t = p.nextToken(); // to move to following FIELD_NAME/END_OBJECT
782794
Object bean;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.fasterxml.jackson.databind.deser;
2+
3+
import com.fasterxml.jackson.databind.BaseMapTest;
4+
import com.fasterxml.jackson.databind.JsonMappingException;
5+
import com.fasterxml.jackson.databind.ObjectMapper;
6+
7+
import java.io.IOException;
8+
9+
public class TestExceptionHandlingWithDefaultDeserialization extends BaseMapTest {
10+
11+
static class Foo {
12+
13+
private Bar bar;
14+
15+
public Foo() {
16+
}
17+
18+
public Bar getBar() {
19+
return bar;
20+
}
21+
}
22+
23+
static class Bar {
24+
25+
private Baz baz;
26+
27+
public Bar() {
28+
}
29+
30+
public Baz getBaz() {
31+
return baz;
32+
}
33+
}
34+
35+
static class Baz {
36+
37+
private String qux;
38+
39+
public Baz() {
40+
}
41+
42+
public String getQux() {
43+
return qux;
44+
}
45+
}
46+
47+
public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException {
48+
// given
49+
ObjectMapper mapper = new ObjectMapper();
50+
String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}";
51+
52+
// when
53+
try {
54+
mapper.readValue(input, Foo.class);
55+
fail("Upsss! Exception has not been thrown.");
56+
} catch (JsonMappingException ex) {
57+
// then
58+
assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]",
59+
ex.getPathReference());
60+
}
61+
}
62+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package com.fasterxml.jackson.databind.deser;
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator;
4+
import com.fasterxml.jackson.annotation.JsonProperty;
5+
import com.fasterxml.jackson.databind.BaseMapTest;
6+
import com.fasterxml.jackson.databind.JsonMappingException;
7+
import com.fasterxml.jackson.databind.ObjectMapper;
8+
9+
import java.io.IOException;
10+
11+
public class TestExceptionHandlingWithJsonCreatorDeserialization extends BaseMapTest {
12+
13+
static class Foo {
14+
15+
private Bar bar;
16+
17+
@JsonCreator
18+
public Foo(@JsonProperty("bar") Bar bar) {
19+
this.bar = bar;
20+
}
21+
22+
public Bar getBar() {
23+
return bar;
24+
}
25+
}
26+
27+
static class Bar {
28+
29+
private Baz baz;
30+
31+
@JsonCreator
32+
public Bar(@JsonProperty("baz") Baz baz) {
33+
this.baz = baz;
34+
}
35+
36+
public Baz getBaz() {
37+
return baz;
38+
}
39+
}
40+
41+
static class Baz {
42+
43+
private String qux;
44+
45+
@JsonCreator
46+
public Baz(@JsonProperty("qux") String qux) {
47+
this.qux = qux;
48+
}
49+
50+
public String getQux() {
51+
return qux;
52+
}
53+
}
54+
55+
public void testShouldThrowJsonMappingExceptionWithPathReference() throws IOException {
56+
// given
57+
ObjectMapper mapper = new ObjectMapper();
58+
String input = "{\"bar\":{\"baz\":{qux:\"quxValue\"))}";
59+
60+
// when
61+
try {
62+
mapper.readValue(input, Foo.class);
63+
fail("Upsss! Exception has not been thrown.");
64+
} catch (JsonMappingException ex) {
65+
// then
66+
assertEquals("com.fasterxml.jackson.databind.deser.Foo[\"bar\"]->com.fasterxml.jackson.databind.deser.Bar[\"baz\"]",
67+
ex.getPathReference());
68+
}
69+
}
70+
}

0 commit comments

Comments
 (0)