Skip to content

Commit e904965

Browse files
Merge findInjectableValues() results in AnnotationIntrospectorPair
As many AnnotationIntrospector implementations use default values for useInput, allow the secondary introspector's useInput value to combine with the primary's id to prevent losing the useInput value. Fixes a special case of FasterXML#962 seen by the GuiceAnnotationInspector in FasterXML/jackson-modules-base#134
1 parent e85f7f0 commit e904965

File tree

2 files changed

+100
-1
lines changed

2 files changed

+100
-1
lines changed

src/main/java/com/fasterxml/jackson/databind/introspect/AnnotationIntrospectorPair.java

+5-1
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,11 @@ public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) {
300300
@Override
301301
public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
302302
JacksonInject.Value r = _primary.findInjectableValue(m);
303-
return (r == null) ? _secondary.findInjectableValue(m) : r;
303+
if (r == null || r.getUseInput() == null) {
304+
JacksonInject.Value secondary = _secondary.findInjectableValue(m);
305+
r = (r == null || secondary == null) ? secondary : r.withUseInput(secondary.getUseInput());
306+
}
307+
return r;
304308
}
305309

306310
@Override

src/test/java/com/fasterxml/jackson/databind/introspect/IntrospectorPairTest.java

+95
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,20 @@
33
import java.lang.annotation.Annotation;
44
import java.util.*;
55

6+
import com.fasterxml.jackson.annotation.JacksonInject;
7+
import com.fasterxml.jackson.annotation.JsonIgnore;
68
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
79
import com.fasterxml.jackson.annotation.JsonInclude;
810

11+
import com.fasterxml.jackson.annotation.JsonProperty;
12+
import com.fasterxml.jackson.annotation.OptBoolean;
913
import com.fasterxml.jackson.core.Version;
1014

1115
import com.fasterxml.jackson.databind.*;
1216
import com.fasterxml.jackson.databind.cfg.MapperConfig;
1317
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
1418
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
19+
import com.fasterxml.jackson.databind.json.JsonMapper;
1520
import com.fasterxml.jackson.databind.jsontype.NamedType;
1621
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
1722
import com.fasterxml.jackson.databind.ser.std.StringSerializer;
@@ -601,4 +606,94 @@ public void testInclusionMerging() throws Exception
601606
assertEquals(JsonInclude.Include.NON_EMPTY, v21.getContentInclusion());
602607
assertEquals(JsonInclude.Include.NON_ABSENT, v21.getValueInclusion());
603608
}
609+
610+
/*
611+
/**********************************************************
612+
/* Introspectors and test for [jackson-modules-base#134]/[databind#962]
613+
/**********************************************************
614+
*/
615+
static class TestIntrospector extends NopAnnotationIntrospector {
616+
@Override
617+
public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
618+
if (m.getRawType() == UnreadableBean.class) {
619+
return JacksonInject.Value.forId("jjj");
620+
}
621+
return null;
622+
}
623+
}
624+
625+
static class TestInjector extends InjectableValues {
626+
@Override
627+
public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) {
628+
if (valueId == "jjj") {
629+
UnreadableBean bean = new UnreadableBean();
630+
bean.setValue(1);
631+
return bean;
632+
}
633+
return null;
634+
}
635+
}
636+
637+
enum SimpleEnum { ONE, TWO }
638+
639+
static class UnreadableBean {
640+
public SimpleEnum value;
641+
642+
public void setValue(SimpleEnum value) {
643+
this.value = value;
644+
}
645+
646+
public void setValue(Integer intValue) {
647+
this.value = SimpleEnum.values()[intValue];
648+
}
649+
650+
public SimpleEnum getValue() {
651+
return value;
652+
}
653+
}
654+
655+
static class ReadableInjectedBean {
656+
public ReadableInjectedBean(@JacksonInject(useInput = OptBoolean.FALSE) UnreadableBean injectBean) {
657+
this.injectBean = injectBean;
658+
}
659+
@JsonProperty
660+
private String foo;
661+
@JsonIgnore
662+
private UnreadableBean injectBean;
663+
}
664+
665+
static class UnreadableInjectedBean {
666+
public UnreadableInjectedBean(@JacksonInject UnreadableBean injectBean) {
667+
this.injectBean = injectBean;
668+
}
669+
@JsonProperty
670+
private String foo;
671+
@JsonIgnore
672+
private UnreadableBean injectBean;
673+
}
674+
675+
public void testMergingIntrospectorsForInjection() throws Exception {
676+
AnnotationIntrospector testIntrospector = new TestIntrospector();
677+
ObjectMapper mapper = new JsonMapper();
678+
mapper.setInjectableValues(new TestInjector());
679+
mapper.setAnnotationIntrospectors(
680+
new AnnotationIntrospectorPair(testIntrospector,
681+
mapper.getSerializationConfig().getAnnotationIntrospector()),
682+
new AnnotationIntrospectorPair(testIntrospector,
683+
mapper.getDeserializationConfig().getAnnotationIntrospector())
684+
);
685+
ReadableInjectedBean bean = mapper.readValue("{\"foo\": \"bob\"}", ReadableInjectedBean.class);
686+
assertEquals("bob", bean.foo);
687+
assertEquals(SimpleEnum.TWO, bean.injectBean.value);
688+
689+
boolean successReadingUnreadableInjectedBean;
690+
try {
691+
UnreadableInjectedBean noBean = mapper.readValue("{\"foo\": \"bob\"}", UnreadableInjectedBean.class);
692+
successReadingUnreadableInjectedBean = true;
693+
} catch (JsonMappingException e) {
694+
successReadingUnreadableInjectedBean = false;
695+
assertTrue(e.getMessage().contains("Conflicting setter definitions"));
696+
}
697+
assertFalse(successReadingUnreadableInjectedBean);
698+
}
604699
}

0 commit comments

Comments
 (0)