Skip to content

Commit

Permalink
fix: Jackson JsonUnwrapped from inherited properties (#435)
Browse files Browse the repository at this point in the history
  • Loading branch information
Nephery authored Mar 9, 2024
1 parent 9bc736a commit ea0e346
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 6 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@

import com.fasterxml.classmate.ResolvedType;
import com.fasterxml.classmate.ResolvedTypeWithMembers;
import com.fasterxml.classmate.members.RawMember;
import com.fasterxml.classmate.members.ResolvedMember;
import com.fasterxml.jackson.annotation.JsonUnwrapped;
import com.fasterxml.jackson.databind.JsonNode;
Expand All @@ -30,6 +29,7 @@
import com.github.victools.jsonschema.generator.SchemaKeyword;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.stream.Stream;
Expand All @@ -43,17 +43,18 @@ public class JsonUnwrappedDefinitionProvider implements CustomDefinitionProvider

@Override
public CustomDefinition provideCustomSchemaDefinition(ResolvedType javaType, SchemaGenerationContext context) {
if (javaType.getMemberFields().stream().noneMatch(this::hasJsonUnwrappedAnnotation)
&& javaType.getMemberMethods().stream().noneMatch(this::hasJsonUnwrappedAnnotation)) {
ResolvedTypeWithMembers typeWithMembers = context.getTypeContext().resolveWithMembers(javaType);

if (Arrays.stream(typeWithMembers.getMemberFields()).noneMatch(this::hasJsonUnwrappedAnnotation)
&& Arrays.stream(typeWithMembers.getMemberMethods()).noneMatch(this::hasJsonUnwrappedAnnotation)) {
// no need for custom handling here, if no relevant annotation is present
return null;
}
// include the target type itself (assuming the annotated members are being ignored then)
ObjectNode definition = context.createStandardDefinition(javaType, this);
ArrayNode allOf = definition.withArray(context.getKeyword(SchemaKeyword.TAG_ALLOF));
// include each annotated member's type considering the optional prefix and/or suffix
ResolvedTypeWithMembers typeWithMembers = context.getTypeContext().resolveWithMembers(javaType);

// include each annotated member's type considering the optional prefix and/or suffix
Stream.concat(Stream.of(typeWithMembers.getMemberFields()), Stream.of(typeWithMembers.getMemberMethods()))
.filter(member -> Optional.ofNullable(member.getAnnotations().get(JsonUnwrapped.class))
.filter(JsonUnwrapped::enabled).isPresent())
Expand All @@ -69,7 +70,7 @@ public CustomDefinition provideCustomSchemaDefinition(ResolvedType javaType, Sch
* @param member field/method to check
* @return whether the given member has an {@code enabled} {@link JsonUnwrapped @JsonUnwrapped} annotation
*/
private boolean hasJsonUnwrappedAnnotation(RawMember member) {
private boolean hasJsonUnwrappedAnnotation(ResolvedMember<?> member) {
for (Annotation annotation : member.getAnnotations()) {
if (annotation instanceof JsonUnwrapped && ((JsonUnwrapped) annotation).enabled()) {
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,8 @@ static class TestClass {
@JsonUnwrapped
public TypeToBeUnwrapped typeToBeUnwrapped;

public TypeWithInheritedFieldToBeUnwrapped typeWithInheritedFieldToBeUnwrapped;

public String ignoredUnannotatedMethod() {
return "nothing";
}
Expand Down Expand Up @@ -158,4 +160,13 @@ static class SubType2 implements BaseType {
static class TypeToBeUnwrapped {
public String unwrappedProperty;
}

static class TypeWithInheritedFieldToBeUnwrapped extends TypeWithFieldToBeUnwrapped {

}

static class TypeWithFieldToBeUnwrapped {
@JsonUnwrapped
public TypeToBeUnwrapped typeToBeUnwrapped;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,14 @@
}
}
},
"typeWithInheritedFieldToBeUnwrapped": {
"type": "object",
"properties": {
"unwrappedProperty": {
"type": "string"
}
}
},
"unwrappedProperty": {
"type": "string"
}
Expand Down

0 comments on commit ea0e346

Please sign in to comment.