Skip to content

Commit

Permalink
Add class hints for Jackson annotations on fields and methods
Browse files Browse the repository at this point in the history
Before this commit, only class level annotations were
processed.

Closes gh-30208
  • Loading branch information
sdeleuze committed Mar 31, 2023
1 parent d451d6a commit 8073259
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 5 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -169,19 +169,17 @@ private void registerJacksonHints(ReflectionHints hints, Class<?> clazz) {
if (sourceField != null) {
hints.registerField(sourceField);
}
registerHintsForClassAttributes(hints, annotation);
}));
ReflectionUtils.doWithMethods(clazz, method ->
forEachJacksonAnnotation(method, annotation -> {
Method sourceMethod = (Method) annotation.getSource();
if (sourceMethod != null) {
hints.registerMethod(sourceMethod, ExecutableMode.INVOKE);
}
registerHintsForClassAttributes(hints, annotation);
}));
forEachJacksonAnnotation(clazz, annotation -> annotation.getRoot().asMap().values().forEach(value -> {
if (value instanceof Class<?> classValue) {
hints.registerType(classValue, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
}));
forEachJacksonAnnotation(clazz, annotation -> registerHintsForClassAttributes(hints, annotation));
}

private void forEachJacksonAnnotation(AnnotatedElement element, Consumer<MergedAnnotation<Annotation>> action) {
Expand All @@ -192,6 +190,14 @@ private void forEachJacksonAnnotation(AnnotatedElement element, Consumer<MergedA
.forEach(action::accept);
}

private void registerHintsForClassAttributes(ReflectionHints hints, MergedAnnotation<Annotation> annotation) {
annotation.getRoot().asMap().values().forEach(value -> {
if (value instanceof Class<?> classValue && value != Void.class) {
hints.registerType(classValue, MemberCategory.INVOKE_DECLARED_CONSTRUCTORS);
}
});
}

/**
* Inner class to avoid a hard dependency on Kotlin at runtime.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,21 @@

package org.springframework.aot.hint;

import java.io.IOException;
import java.lang.reflect.Type;
import java.time.LocalDate;
import java.util.List;
import java.util.Set;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import com.fasterxml.jackson.databind.deser.std.StdDeserializer;
import org.junit.jupiter.api.Test;

import org.springframework.aot.hint.predicate.RuntimeHintsPredicates;
Expand Down Expand Up @@ -265,6 +271,15 @@ void registerTypeForJacksonCustomStrategy() {
.accepts(this.hints);
}

@Test
void registerTypeForAnnotationOnMethodAndField() {
bindingRegistrar.registerReflectionHints(this.hints.reflection(), SampleClassWithJsonProperty.class);
assertThat(RuntimeHintsPredicates.reflection().onType(CustomDeserializer1.class).withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.accepts(this.hints);
assertThat(RuntimeHintsPredicates.reflection().onType(CustomDeserializer2.class).withMemberCategory(MemberCategory.INVOKE_DECLARED_CONSTRUCTORS))
.accepts(this.hints);
}


static class SampleEmptyClass {
}
Expand Down Expand Up @@ -359,9 +374,11 @@ public String getNameProperty() {
static class SampleClassWithJsonProperty {

@JsonProperty
@JsonDeserialize(using = CustomDeserializer1.class)
private String privateField = "";

@JsonProperty
@JsonDeserialize(using = CustomDeserializer2.class)
String packagePrivateMethod() {
return "";
}
Expand Down Expand Up @@ -393,4 +410,28 @@ public SampleRecordWithJacksonCustomStrategy build() {

}

static class CustomDeserializer1 extends StdDeserializer<LocalDate> {

public CustomDeserializer1() {
super(CustomDeserializer1.class);
}

@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
return null;
}
}

static class CustomDeserializer2 extends StdDeserializer<LocalDate> {

public CustomDeserializer2() {
super(CustomDeserializer2.class);
}

@Override
public LocalDate deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
return null;
}
}

}

0 comments on commit 8073259

Please sign in to comment.