diff --git a/pom.xml b/pom.xml index 32a0c87..6a3cec6 100644 --- a/pom.xml +++ b/pom.xml @@ -37,7 +37,9 @@ introspection of method/constructor parameter names, without having to add expli com/fasterxml/jackson/module/paramnames ${project.groupId}.paramnames - 3.3.0 + + 3.4.0 + 1.10.19 @@ -58,6 +60,12 @@ introspection of method/constructor parameter names, without having to add expli ${assertj-core.version} test + + org.mockito + mockito-core + ${mockito-core.version} + test + diff --git a/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterExtractor.java b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterExtractor.java new file mode 100644 index 0000000..5e63b19 --- /dev/null +++ b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterExtractor.java @@ -0,0 +1,11 @@ +package com.fasterxml.jackson.module.paramnames; + +import java.lang.reflect.Executable; +import java.lang.reflect.Parameter; + +class ParameterExtractor { + + public Parameter[] getParameters(Executable executable) { + return executable.getParameters(); + } +} diff --git a/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospector.java b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospector.java index 4ac3081..3726edf 100644 --- a/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospector.java +++ b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospector.java @@ -4,7 +4,8 @@ import com.fasterxml.jackson.databind.AnnotationIntrospector; import com.fasterxml.jackson.databind.introspect.*; -import java.lang.reflect.*; +import java.lang.reflect.MalformedParametersException; +import java.lang.reflect.Parameter; /** * Introspector that uses parameter name information provided by the Java Reflection API additions in Java 8 to @@ -14,15 +15,16 @@ * @see AnnotationIntrospector * @see Parameter */ -class ParameterNamesAnnotationIntrospector extends NopAnnotationIntrospector -{ +class ParameterNamesAnnotationIntrospector extends NopAnnotationIntrospector { private static final long serialVersionUID = 1L; private final JsonCreator.Mode creatorBinding; + private final ParameterExtractor parameterExtractor; - ParameterNamesAnnotationIntrospector(JsonCreator.Mode creatorBinding) { + ParameterNamesAnnotationIntrospector(JsonCreator.Mode creatorBinding, ParameterExtractor parameterExtractor) { this.creatorBinding = creatorBinding; + this.parameterExtractor = parameterExtractor; } @Override @@ -44,26 +46,28 @@ public JsonCreator.Mode findCreatorBinding(Annotated a) { return creatorBinding; } - /** - * Returns the parameter name, or {@code null} if it could not be determined. - * - * @param annotatedParameter containing constructor or method from which {@link Parameter} can be extracted - * - * @return name or {@code null} if parameter could not be determined - */ private String findParameterName(AnnotatedParameter annotatedParameter) { - AnnotatedWithParams owner = annotatedParameter.getOwner(); Parameter[] params; - - if (owner instanceof AnnotatedConstructor) { - params = ((AnnotatedConstructor) owner).getAnnotated().getParameters(); - } else if (owner instanceof AnnotatedMethod) { - params = ((AnnotatedMethod) owner).getAnnotated().getParameters(); - } else { + try { + params = getParameters(annotatedParameter.getOwner()); + } catch (MalformedParametersException e) { return null; } + Parameter p = params[annotatedParameter.getIndex()]; return p.isNamePresent() ? p.getName() : null; } + + private Parameter[] getParameters(AnnotatedWithParams owner) { + if (owner instanceof AnnotatedConstructor) { + return parameterExtractor.getParameters(((AnnotatedConstructor) owner).getAnnotated()); + } + + if (owner instanceof AnnotatedMethod) { + return parameterExtractor.getParameters(((AnnotatedMethod) owner).getAnnotated()); + } + + return null; + } } diff --git a/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesModule.java b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesModule.java index afbf8e3..0b7d60c 100644 --- a/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesModule.java +++ b/src/main/java/com/fasterxml/jackson/module/paramnames/ParameterNamesModule.java @@ -22,7 +22,7 @@ public ParameterNamesModule() { @Override public void setupModule(SetupContext context) { super.setupModule(context); - context.insertAnnotationIntrospector(new ParameterNamesAnnotationIntrospector(creatorBinding)); + context.insertAnnotationIntrospector(new ParameterNamesAnnotationIntrospector(creatorBinding, new ParameterExtractor())); } @Override diff --git a/src/test/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospectorTest.java b/src/test/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospectorTest.java index 91eebe7..8c42d56 100644 --- a/src/test/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospectorTest.java +++ b/src/test/java/com/fasterxml/jackson/module/paramnames/ParameterNamesAnnotationIntrospectorTest.java @@ -4,47 +4,86 @@ import com.fasterxml.jackson.databind.introspect.AnnotatedConstructor; import com.fasterxml.jackson.databind.introspect.AnnotatedMethod; import com.fasterxml.jackson.databind.introspect.AnnotatedParameter; - +import org.junit.Before; import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.BDDMockito; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; import java.lang.reflect.Constructor; +import java.lang.reflect.MalformedParametersException; import java.lang.reflect.Method; +import java.lang.reflect.Parameter; -import static org.junit.Assert.assertEquals; +import static org.assertj.core.api.BDDAssertions.then; +import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; /** * @author Lovro Pandzic */ +@RunWith(MockitoJUnitRunner.class) public class ParameterNamesAnnotationIntrospectorTest { - private final ParameterNamesAnnotationIntrospector PN_AI = new ParameterNamesAnnotationIntrospector(JsonCreator.Mode.DEFAULT); + @Mock + private ParameterExtractor parameterExtractor; + + private ParameterNamesAnnotationIntrospector introspector; + + @Before + public void setUp() throws Exception { + introspector = new ParameterNamesAnnotationIntrospector(JsonCreator.Mode.DEFAULT, parameterExtractor); + } @Test public void shouldFindParameterNameFromConstructorForLegalIndex() throws Exception { - Constructor ctor = ImmutableBean.class.getConstructor(String.class, Integer.class); - - assertEquals("name", ctor.getParameters()[0].getName()); - AnnotatedConstructor owner = new AnnotatedConstructor(null, ctor, null, null); + // given + Constructor givenConstructor = ImmutableBean.class.getConstructor(String.class, Integer.class); + Parameter[] givenParameters = givenConstructor.getParameters(); + AnnotatedConstructor owner = new AnnotatedConstructor(null, givenConstructor, null, null); AnnotatedParameter annotatedParameter = new AnnotatedParameter(owner, null, null, 0); - - String propertyName = PN_AI.findImplicitPropertyName(annotatedParameter); + given(parameterExtractor.getParameters(any())).willReturn(givenParameters); + + // when + String actual = introspector.findImplicitPropertyName(annotatedParameter); - assertEquals("name", propertyName); + then(actual).isEqualTo("name"); + BDDMockito.then(parameterExtractor).should().getParameters(givenConstructor); } @Test public void shouldFindParameterNameFromMethodForLegalIndex() throws Exception { - Method method = ImmutableBeanWithStaticFactory.class.getMethod("of", String.class, Integer.class); + // given + Method givenMethod = ImmutableBeanWithStaticFactory.class.getMethod("of", String.class, Integer.class); + Parameter[] givenParameters = givenMethod.getParameters(); + AnnotatedMethod owner = new AnnotatedMethod(null, givenMethod, null, null); + AnnotatedParameter annotatedParameter = new AnnotatedParameter(owner, null, null, 0); + given(parameterExtractor.getParameters(any())).willReturn(givenParameters); + + // when + String actual = introspector.findImplicitPropertyName(annotatedParameter); + + // then + then(actual).isEqualTo("name"); + BDDMockito.then(parameterExtractor).should().getParameters(givenMethod); + } + + @Test + public void shouldReturnNullForMalformedParametersException() throws Exception { - assertEquals("name", method.getParameters()[0].getName()); - - AnnotatedMethod owner = new AnnotatedMethod(null, method, null, null); + // given + Constructor givenConstructor = ImmutableBean.class.getConstructor(String.class, Integer.class); + AnnotatedConstructor owner = new AnnotatedConstructor(null, givenConstructor, null, null); AnnotatedParameter annotatedParameter = new AnnotatedParameter(owner, null, null, 0); + given(parameterExtractor.getParameters(any())).willThrow(new MalformedParametersException()); - String propertyName = PN_AI.findImplicitPropertyName(annotatedParameter); + // when + String actual = introspector.findImplicitPropertyName(annotatedParameter); - assertEquals("name", propertyName); + then(actual).isNull(); + BDDMockito.then(parameterExtractor).should().getParameters(givenConstructor); } }