Skip to content

Commit 8e3f5d2

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 #962 seen by the GuiceAnnotationInspector in FasterXML/jackson-modules-base#134
1 parent e85f7f0 commit 8e3f5d2

File tree

2 files changed

+108
-1
lines changed

2 files changed

+108
-1
lines changed

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

Lines changed: 5 additions & 1 deletion
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
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package com.fasterxml.jackson.databind.introspect;
2+
3+
import com.fasterxml.jackson.annotation.JacksonInject;
4+
import com.fasterxml.jackson.annotation.JsonIgnore;
5+
import com.fasterxml.jackson.annotation.JsonProperty;
6+
import com.fasterxml.jackson.annotation.OptBoolean;
7+
import com.fasterxml.jackson.databind.AnnotationIntrospector;
8+
import com.fasterxml.jackson.databind.BeanProperty;
9+
import com.fasterxml.jackson.databind.DeserializationContext;
10+
import com.fasterxml.jackson.databind.InjectableValues;
11+
import com.fasterxml.jackson.databind.JsonMappingException;
12+
import com.fasterxml.jackson.databind.ObjectMapper;
13+
import com.fasterxml.jackson.databind.json.JsonMapper;
14+
import junit.framework.TestCase;
15+
16+
public class AnnotationIntrospectorPairTest extends TestCase {
17+
18+
static class TestIntrospector extends NopAnnotationIntrospector {
19+
@Override
20+
public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
21+
if (m.getRawType() == UnreadableBean.class) {
22+
return JacksonInject.Value.forId("jjj");
23+
}
24+
return null;
25+
}
26+
}
27+
28+
static class TestInjector extends InjectableValues {
29+
30+
@Override
31+
public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) {
32+
if (valueId == "jjj") {
33+
UnreadableBean bean = new UnreadableBean();
34+
bean.setValue(1);
35+
return bean;
36+
}
37+
return null;
38+
}
39+
}
40+
41+
enum SimpleEnum { ONE, TWO }
42+
43+
static class UnreadableBean {
44+
public SimpleEnum value;
45+
46+
public void setValue(SimpleEnum value) {
47+
this.value = value;
48+
}
49+
50+
public void setValue(Integer intValue) {
51+
this.value = SimpleEnum.values()[intValue];
52+
}
53+
54+
public SimpleEnum getValue() {
55+
return value;
56+
}
57+
}
58+
59+
static class ReadableInjectedBean {
60+
public ReadableInjectedBean(@JacksonInject(useInput = OptBoolean.FALSE) UnreadableBean injectBean) {
61+
this.injectBean = injectBean;
62+
}
63+
@JsonProperty
64+
private String foo;
65+
@JsonIgnore
66+
private UnreadableBean injectBean;
67+
}
68+
69+
static class UnreadableInjectedBean {
70+
public UnreadableInjectedBean(@JacksonInject UnreadableBean injectBean) {
71+
this.injectBean = injectBean;
72+
}
73+
@JsonProperty
74+
private String foo;
75+
@JsonIgnore
76+
private UnreadableBean injectBean;
77+
}
78+
79+
public void testMergingIntrospectors() throws Exception {
80+
AnnotationIntrospector testInstrospector = new TestIntrospector();
81+
ObjectMapper mapper = new JsonMapper();
82+
mapper.setInjectableValues(new TestInjector());
83+
mapper.setAnnotationIntrospectors(
84+
new AnnotationIntrospectorPair(testInstrospector,
85+
mapper.getSerializationConfig().getAnnotationIntrospector()),
86+
new AnnotationIntrospectorPair(testInstrospector,
87+
mapper.getDeserializationConfig().getAnnotationIntrospector())
88+
);
89+
ReadableInjectedBean bean = mapper.readValue("{\"foo\": \"bob\"}", ReadableInjectedBean.class);
90+
assertEquals("bob", bean.foo);
91+
assertEquals(SimpleEnum.TWO, bean.injectBean.value);
92+
93+
boolean successReadingUnreadableInjectedBean;
94+
try {
95+
UnreadableInjectedBean noBean = mapper.readValue("{\"foo\": \"bob\"}", UnreadableInjectedBean.class);
96+
successReadingUnreadableInjectedBean = true;
97+
} catch (JsonMappingException e) {
98+
successReadingUnreadableInjectedBean = false;
99+
assertTrue(e.getMessage().contains("Conflicting setter definitions"));
100+
}
101+
assertFalse(successReadingUnreadableInjectedBean);
102+
}
103+
}

0 commit comments

Comments
 (0)