Skip to content

Commit

Permalink
Merge findInjectableValues() results in AnnotationIntrospectorPair (#…
Browse files Browse the repository at this point in the history
…3146)

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
  • Loading branch information
josephlbarnett authored May 7, 2021
1 parent e85f7f0 commit e0b74c5
Show file tree
Hide file tree
Showing 2 changed files with 100 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -300,7 +300,11 @@ public NameTransformer findUnwrappingNameTransformer(AnnotatedMember member) {
@Override
public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
JacksonInject.Value r = _primary.findInjectableValue(m);
return (r == null) ? _secondary.findInjectableValue(m) : r;
if (r == null || r.getUseInput() == null) {
JacksonInject.Value secondary = _secondary.findInjectableValue(m);
r = (r == null || secondary == null) ? secondary : r.withUseInput(secondary.getUseInput());
}
return r;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,20 @@
import java.lang.annotation.Annotation;
import java.util.*;

import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.OptBoolean;
import com.fasterxml.jackson.core.Version;

import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.cfg.MapperConfig;
import com.fasterxml.jackson.databind.deser.std.StringDeserializer;
import com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.jsontype.NamedType;
import com.fasterxml.jackson.databind.jsontype.TypeResolverBuilder;
import com.fasterxml.jackson.databind.ser.std.StringSerializer;
Expand Down Expand Up @@ -601,4 +606,94 @@ public void testInclusionMerging() throws Exception
assertEquals(JsonInclude.Include.NON_EMPTY, v21.getContentInclusion());
assertEquals(JsonInclude.Include.NON_ABSENT, v21.getValueInclusion());
}

/*
/**********************************************************
/* Introspectors and test for [jackson-modules-base#134]/[databind#962]
/**********************************************************
*/
static class TestIntrospector extends NopAnnotationIntrospector {
@Override
public JacksonInject.Value findInjectableValue(AnnotatedMember m) {
if (m.getRawType() == UnreadableBean.class) {
return JacksonInject.Value.forId("jjj");
}
return null;
}
}

static class TestInjector extends InjectableValues {
@Override
public Object findInjectableValue(Object valueId, DeserializationContext ctxt, BeanProperty forProperty, Object beanInstance) {
if (valueId == "jjj") {
UnreadableBean bean = new UnreadableBean();
bean.setValue(1);
return bean;
}
return null;
}
}

enum SimpleEnum { ONE, TWO }

static class UnreadableBean {
public SimpleEnum value;

public void setValue(SimpleEnum value) {
this.value = value;
}

public void setValue(Integer intValue) {
this.value = SimpleEnum.values()[intValue];
}

public SimpleEnum getValue() {
return value;
}
}

static class ReadableInjectedBean {
public ReadableInjectedBean(@JacksonInject(useInput = OptBoolean.FALSE) UnreadableBean injectBean) {
this.injectBean = injectBean;
}
@JsonProperty
private String foo;
@JsonIgnore
private UnreadableBean injectBean;
}

static class UnreadableInjectedBean {
public UnreadableInjectedBean(@JacksonInject UnreadableBean injectBean) {
this.injectBean = injectBean;
}
@JsonProperty
private String foo;
@JsonIgnore
private UnreadableBean injectBean;
}

public void testMergingIntrospectorsForInjection() throws Exception {
AnnotationIntrospector testIntrospector = new TestIntrospector();
ObjectMapper mapper = new JsonMapper();
mapper.setInjectableValues(new TestInjector());
mapper.setAnnotationIntrospectors(
new AnnotationIntrospectorPair(testIntrospector,
mapper.getSerializationConfig().getAnnotationIntrospector()),
new AnnotationIntrospectorPair(testIntrospector,
mapper.getDeserializationConfig().getAnnotationIntrospector())
);
ReadableInjectedBean bean = mapper.readValue("{\"foo\": \"bob\"}", ReadableInjectedBean.class);
assertEquals("bob", bean.foo);
assertEquals(SimpleEnum.TWO, bean.injectBean.value);

boolean successReadingUnreadableInjectedBean;
try {
UnreadableInjectedBean noBean = mapper.readValue("{\"foo\": \"bob\"}", UnreadableInjectedBean.class);
successReadingUnreadableInjectedBean = true;
} catch (JsonMappingException e) {
successReadingUnreadableInjectedBean = false;
assertTrue(e.getMessage().contains("Conflicting setter definitions"));
}
assertFalse(successReadingUnreadableInjectedBean);
}
}

0 comments on commit e0b74c5

Please sign in to comment.