Skip to content

Commit

Permalink
Fill in the required property based on annotations, fixes #26
Browse files Browse the repository at this point in the history
  • Loading branch information
andriy-dmytruk committed Apr 29, 2024
1 parent ce23ba5 commit f0b4271
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,9 @@ public static void setBeanSchemaProperties(ClassElement element, VisitorContext
}
context.createdSchemasByType().put(element.getGenericType().getName(), schema);
for (PropertyElement property: element.getBeanProperties()) {
schema.putProperty(property.getName(), createSchema(property, visitorContext, context));
Schema propertySchema = createSchema(property, visitorContext, context);
propertySchema.setSourceElement(property);
schema.putProperty(property.getName(), propertySchema);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,19 +26,23 @@
import java.math.BigDecimal;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

/**
* An aggregator for adding information from the validation annotations.
*/
@Internal
public class ValidationInfoAggregator implements SchemaInfoAggregator {

private static final String JAKARTA_ANNOTATION_PREFIX = "jakarta.annotation.";
private static final String JAKARTA_VALIDATION_PREFIX = "jakarta.validation.constraints.";
private static final String NULLABLE_ANN = JAKARTA_ANNOTATION_PREFIX + "Nullable";
private static final String NON_NULL_ANN = JAKARTA_ANNOTATION_PREFIX + "Nonnull";
private static final String NULL_ANN = JAKARTA_VALIDATION_PREFIX + "Null";
private static final String NULLABLE_ANN = "jakarta.annotation.Nullable";
private static final String ASSERT_FALSE_ANN = JAKARTA_VALIDATION_PREFIX + "AssertFalse";
private static final String ASSERT_TRUE_ANN = JAKARTA_VALIDATION_PREFIX + "AssertTrue";
private static final String NOT_EMPTY_ANN = JAKARTA_VALIDATION_PREFIX + "NotEmpty";
private static final String NOT_NULL_ANN = JAKARTA_VALIDATION_PREFIX + "NotNull";
private static final String SIZE_ANN = JAKARTA_VALIDATION_PREFIX + "Size";
private static final String NOT_BLANK_ANN = JAKARTA_VALIDATION_PREFIX + "NotBlank";
private static final String NEGATIVE_ANN = JAKARTA_VALIDATION_PREFIX + "Negative";
Expand Down Expand Up @@ -69,6 +73,8 @@ public Schema addInfo(TypedElement element, Schema schema, VisitorContext visito
visitorContext.warn("Could not add annotation " + ann + " to schema as it is not supported by the JacksonInfoAggregator", element)
);

addRequiredPropertiesInfo(element.getGenericType(), schema);

ClassElement type = element.getGenericType();
if (element.hasAnnotation(NULL_ANN + LIST_SUFFIX)) {
schema.setType(List.of(Schema.Type.NULL));
Expand Down Expand Up @@ -163,4 +169,18 @@ public Schema addInfo(TypedElement element, Schema schema, VisitorContext visito
return schema;
}

private void addRequiredPropertiesInfo(ClassElement element, Schema schema) {
if (schema.getProperties() != null) {
for (Entry<String, Schema> property: schema.getProperties().entrySet()) {
TypedElement sourceElement = property.getValue().getSourceElement();
if (sourceElement.hasAnnotation(NOT_NULL_ANN + LIST_SUFFIX)
|| sourceElement.hasAnnotation(NON_NULL_ANN)
) {
schema.addRequired(property.getKey());
}
}
}
}


}
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,11 @@
package io.micronaut.jsonschema.visitor.model;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonValue;
import io.micronaut.core.annotation.Internal;
import io.micronaut.inject.ast.TypedElement;

import java.util.ArrayList;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -97,6 +99,9 @@ public final class Schema {

private Schema not;

@JsonIgnore
private TypedElement sourceElement;

public String getTitle() {
return title;
}
Expand Down Expand Up @@ -365,6 +370,14 @@ public Schema setRequired(List<String> required) {
return this;
}

public Schema addRequired(String requiredProperty) {
if (required == null) {
required = new ArrayList<>();
}
this.required.add(requiredProperty);
return this;
}

public Schema getAdditionalProperties() {
return additionalProperties;
}
Expand Down Expand Up @@ -455,6 +468,15 @@ public Schema setNot(Schema not) {
return this;
}

public TypedElement getSourceElement() {
return sourceElement;
}

public Schema setSourceElement(TypedElement sourceElement) {
this.sourceElement = sourceElement;
return this;
}

/**
* The type of schema exactly matching a primitive JSON type.
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -304,6 +304,34 @@ class JsonSchemaVisitorSpec extends AbstractJsonSchemaSpec {
schema.properties['digits'].multipleOf == 0.0001
}

void "required properties schema"() {
given:
def schema = buildJsonSchema('test.ClownFish', 'clown-fish', """
package test;
import io.micronaut.core.annotation.NonNull;
import io.micronaut.jsonschema.JsonSchema;
import jakarta.annotation.Nonnull;
import jakarta.validation.constraints.*;
@JsonSchema
public record ClownFish(
@Nonnull
String name,
@NotNull
String color,
@NonNull
Double weight,
Integer age
) {
}
""")

expect:
schema.title == "ClownFish"
schema.required == ['name', 'color', 'weight']
}

void "class schema with documentation"() {
given:
def schema = buildJsonSchema('test.Heron', 'heron', """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,4 +45,4 @@ private static Stream<Arguments> provideInvalid() {
Arguments.of(new Possum("Bob", List.of(new Possum("", null, null)), null) , "/children/0/name: must be at least 1 characters long")
);
}
}
}

0 comments on commit f0b4271

Please sign in to comment.