Skip to content

Commit 16d7725

Browse files
committed
more tweaking for handling of static inner class deserialization (or failure thereof)
1 parent 58a7f7b commit 16d7725

File tree

5 files changed

+46
-63
lines changed

5 files changed

+46
-63
lines changed

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

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -396,8 +396,6 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config
396396
Map<AnnotatedWithParams,BeanPropertyDefinition[]> creatorParams)
397397
throws JsonMappingException
398398
{
399-
final boolean isNonStatic = ClassUtil.isNonStaticInnerClass(beanDesc.getBeanClass());
400-
401399
// First things first: the "default constructor" (zero-arg
402400
// constructor; whether implicit or explicit) is NOT included
403401
// in list of constructors, so needs to be handled separately.
@@ -408,23 +406,24 @@ public ValueInstantiator _valueInstantiatorInstance(DeserializationConfig config
408406
}
409407
}
410408

409+
// 25-Jan-2017, tatu: As per [databind#1501], [databind#1502], [databind#1503], best
410+
// for now to skip attempts at using anything but no-args constructor (see
411+
// `InnerClassProperty` construction for that)
412+
final boolean isNonStaticInnerClass = ClassUtil.isNonStaticInnerClass(beanDesc.getBeanClass());
413+
if (isNonStaticInnerClass) {
414+
// TODO: look for `@JsonCreator` annotated ones, throw explicit exception?
415+
return;
416+
}
417+
411418
// may need to keep track for [#725]
412419
List<AnnotatedConstructor> implicitCtors = null;
413420
for (AnnotatedConstructor ctor : beanDesc.getConstructors()) {
414421
final boolean isCreator = intr.hasCreatorAnnotation(ctor);
415422
BeanPropertyDefinition[] propDefs = creatorParams.get(ctor);
416-
int argCount = ctor.getParameterCount();
417-
418-
// 24-Jan-2017, tatu: Handling of constructors for non-static inner classes
419-
// cause nothing but grief (see [databind#1503] for example)... ugh.
420-
/*
421-
if (isNonStatic) {
422-
--argCount;
423-
}
424-
*/
423+
final int argCount = ctor.getParameterCount();
425424

426425
// some single-arg factory methods (String, number) are auto-detected
427-
if ((argCount == 1) && !isNonStatic) {
426+
if ((argCount == 1) && !isNonStaticInnerClass) {
428427
BeanPropertyDefinition argDef = (propDefs == null) ? null : propDefs[0];
429428
boolean useProps = _checkIfCreatorPropertyBased(intr, ctor, argDef);
430429

@@ -853,10 +852,6 @@ protected SettableBeanProperty constructCreatorProperty(DeserializationContext c
853852
// existing unit tests fail. Still seems like the right thing to do.
854853
java.lang.reflect.Type paramType = param.getParameterType();
855854
JavaType t0 = beanDesc.resolveType(paramType);
856-
if (t0 == null) {
857-
System.err.println("type of: "+param.getClass());
858-
// throw new Error("FOOBAR: param #"+index+" type? "+paramType);
859-
}
860855
BeanProperty.Std property = new BeanProperty.Std(name, t0,
861856
intr.findWrapperName(param),
862857
beanDesc.getClassAnnotations(), param, metadata);

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

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -769,7 +769,7 @@ protected SettableBeanProperty _resolveUnwrappedProperty(DeserializationContext
769769
*/
770770
protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationContext ctxt,
771771
SettableBeanProperty prop)
772-
{
772+
{
773773
/* Should we encounter a property that has non-static inner-class
774774
* as value, we need to add some more magic to find the "hidden" constructor...
775775
*/
@@ -780,16 +780,19 @@ protected SettableBeanProperty _resolveInnerClassValuedProperty(DeserializationC
780780
ValueInstantiator vi = bd.getValueInstantiator();
781781
if (!vi.canCreateUsingDefault()) { // no default constructor
782782
Class<?> valueClass = prop.getType().getRawClass();
783+
// NOTE: almost same as `isNonStaticInnerClass()` but need to know enclosing...
783784
Class<?> enclosing = ClassUtil.getOuterClass(valueClass);
784785
// and is inner class of the bean class...
785-
if (enclosing != null && enclosing == _beanType.getRawClass()) {
786+
if ((enclosing != null) && (enclosing == _beanType.getRawClass())) {
786787
for (Constructor<?> ctor : valueClass.getConstructors()) {
787788
Class<?>[] paramTypes = ctor.getParameterTypes();
788-
if (paramTypes.length == 1 && paramTypes[0] == enclosing) {
789-
if (ctxt.canOverrideAccessModifiers()) {
790-
ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
789+
if (paramTypes.length == 1) {
790+
if (enclosing.equals(paramTypes[0])) {
791+
if (ctxt.canOverrideAccessModifiers()) {
792+
ClassUtil.checkAndFixAccess(ctor, ctxt.isEnabled(MapperFeature.OVERRIDE_PUBLIC_ACCESS_MODIFIERS));
793+
}
794+
return new InnerClassProperty(prop, ctor);
791795
}
792-
return new InnerClassProperty(prop, ctor);
793796
}
794797
}
795798
}

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -149,10 +149,10 @@ public JsonDeserializer<Object> createBuilderBasedDeserializer(
149149
Class<?> builderClass)
150150
throws JsonMappingException
151151
{
152-
// First: need a BeanDescription for builder class
153-
JavaType builderType = ctxt.constructType(builderClass);
154-
BeanDescription builderDesc = ctxt.getConfig().introspectForBuilder(builderType);
155-
return buildBuilderBasedDeserializer(ctxt, valueType, builderDesc);
152+
// First: need a BeanDescription for builder class
153+
JavaType builderType = ctxt.constructType(builderClass);
154+
BeanDescription builderDesc = ctxt.getConfig().introspectForBuilder(builderType);
155+
return buildBuilderBasedDeserializer(ctxt, valueType, builderDesc);
156156
}
157157

158158
/**

src/test/java/com/fasterxml/jackson/databind/creators/InnerClassCreatorTest.java

Lines changed: 0 additions & 36 deletions
This file was deleted.

src/test/java/com/fasterxml/jackson/failing/InnerClassCreator1502Test.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,21 @@
77
// for [databind#1502], [databind#1503]
88
public class InnerClassCreator1502Test extends BaseMapTest
99
{
10+
static class Something1501 {
11+
public InnerSomething a;
12+
13+
// important: must name the parameter (param names module, or explicit)
14+
@JsonCreator
15+
public Something1501(@JsonProperty("a") InnerSomething a) { this.a = a; }
16+
17+
public Something1501(boolean bogus) { a = new InnerSomething(); }
18+
19+
class InnerSomething {
20+
@JsonCreator
21+
public InnerSomething() { }
22+
}
23+
}
24+
1025
static class Something1502 {
1126
@JsonProperty
1227
public InnerSomething1502 a;
@@ -18,7 +33,6 @@ class InnerSomething1502 {
1833
@JsonCreator
1934
public InnerSomething1502() {}
2035
}
21-
2236
}
2337

2438
static class Broken1503 {
@@ -39,6 +53,13 @@ static class Generic<T> {
3953
MAPPER.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
4054
}
4155

56+
// Used to trigger `ArrayIndexOutOfBoundsException` for missing creator property index
57+
public void testIssue1501() throws Exception
58+
{
59+
String ser = MAPPER.writeValueAsString(new Something1501(false));
60+
MAPPER.readValue(ser, Something1501.class);
61+
}
62+
4263
public void testIssue1502() throws Exception
4364
{
4465
String ser = MAPPER.writeValueAsString(new Something1502(null));

0 commit comments

Comments
 (0)