com.networknt.schema.ItemsValidator202012 Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of json-schema-validator Show documentation
Show all versions of json-schema-validator Show documentation
A json schema validator that supports draft v4, v6, v7, v2019-09 and v2020-12
/*
* Copyright (c) 2016 Network New Technologies Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.networknt.schema;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.node.ArrayNode;
import com.networknt.schema.annotation.JsonNodeAnnotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.*;
/**
* {@link JsonValidator} for items from V2012-12.
*/
public class ItemsValidator202012 extends BaseJsonValidator {
private static final Logger logger = LoggerFactory.getLogger(ItemsValidator202012.class);
private final JsonSchema schema;
private final int prefixCount;
private final boolean additionalItems;
private Boolean hasUnevaluatedItemsValidator = null;
public ItemsValidator202012(SchemaLocation schemaLocation, JsonNodePath evaluationPath, JsonNode schemaNode,
JsonSchema parentSchema, ValidationContext validationContext) {
super(schemaLocation, evaluationPath, schemaNode, parentSchema, ValidatorTypeCode.ITEMS_202012,
validationContext);
JsonNode prefixItems = parentSchema.getSchemaNode().get("prefixItems");
if (prefixItems instanceof ArrayNode) {
this.prefixCount = prefixItems.size();
} else if (null == prefixItems) {
this.prefixCount = 0;
} else {
throw new IllegalArgumentException("The value of 'prefixItems' must be an array of JSON Schema.");
}
if (schemaNode.isObject() || schemaNode.isBoolean()) {
this.schema = validationContext.newSchema(schemaLocation, evaluationPath, schemaNode, parentSchema);
} else {
throw new IllegalArgumentException("The value of 'items' MUST be a valid JSON Schema.");
}
this.additionalItems = schemaNode.isBoolean() ? schemaNode.booleanValue() : true;
}
@Override
public Set validate(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
JsonNodePath instanceLocation) {
debug(logger, node, rootNode, instanceLocation);
// ignores non-arrays
if (node.isArray()) {
Set errors = new LinkedHashSet<>();
// Collection evaluatedItems = executionContext.getCollectorContext().getEvaluatedItems();
boolean evaluated = false;
for (int i = this.prefixCount; i < node.size(); ++i) {
JsonNodePath path = instanceLocation.append(i);
// validate with item schema (the whole array has the same item schema)
Set results = null;
if (additionalItems) {
results = this.schema.validate(executionContext, node.get(i), rootNode, path);
} else {
// This handles the case where "items": false as the boolean false schema doesn't
// generate a helpful message
int x = i;
results = Collections.singleton(message().instanceNode(node).instanceLocation(instanceLocation)
.locale(executionContext.getExecutionConfig().getLocale())
.failFast(executionContext.isFailFast()).arguments(x).build());
}
if (results.isEmpty()) {
// evaluatedItems.add(path);
} else {
errors.addAll(results);
}
evaluated = true;
}
if (evaluated) {
if (collectAnnotations() || collectAnnotations(executionContext)) {
// Applies to all
executionContext.getAnnotations()
.put(JsonNodeAnnotation.builder().instanceLocation(instanceLocation)
.evaluationPath(this.evaluationPath).schemaLocation(this.schemaLocation)
.keyword(getKeyword()).value(true).build());
}
}
return errors.isEmpty() ? Collections.emptySet() : Collections.unmodifiableSet(errors);
} else {
return Collections.emptySet();
}
}
@Override
public Set walk(ExecutionContext executionContext, JsonNode node, JsonNode rootNode,
JsonNodePath instanceLocation, boolean shouldValidateSchema) {
Set validationMessages = new LinkedHashSet<>();
if (node instanceof ArrayNode) {
ArrayNode arrayNode = (ArrayNode) node;
JsonNode defaultNode = null;
if (this.validationContext.getConfig().getApplyDefaultsStrategy().shouldApplyArrayDefaults()
&& this.schema != null) {
defaultNode = this.schema.getSchemaNode().get("default");
}
for (int i = this.prefixCount; i < node.size(); ++i) {
JsonNode n = node.get(i);
if (n.isNull() && defaultNode != null) {
arrayNode.set(i, defaultNode);
n = defaultNode;
}
// Walk the schema.
walkSchema(executionContext, this.schema, n, rootNode, instanceLocation.append(i), shouldValidateSchema,
validationMessages);
}
} else {
walkSchema(executionContext, this.schema, node, rootNode, instanceLocation, shouldValidateSchema,
validationMessages);
}
return validationMessages;
}
private void walkSchema(ExecutionContext executionContext, JsonSchema walkSchema, JsonNode node, JsonNode rootNode,
JsonNodePath instanceLocation, boolean shouldValidateSchema, Set validationMessages) {
//@formatter:off
boolean executeWalk = this.validationContext.getConfig().getItemWalkListenerRunner().runPreWalkListeners(
executionContext,
ValidatorTypeCode.ITEMS.getValue(),
node,
rootNode,
instanceLocation,
walkSchema.getEvaluationPath(),
walkSchema.getSchemaLocation(),
walkSchema.getSchemaNode(),
walkSchema.getParentSchema(), this.validationContext, this.validationContext.getJsonSchemaFactory()
);
if (executeWalk) {
validationMessages.addAll(walkSchema.walk(executionContext, node, rootNode, instanceLocation, shouldValidateSchema));
}
this.validationContext.getConfig().getItemWalkListenerRunner().runPostWalkListeners(
executionContext,
ValidatorTypeCode.ITEMS.getValue(),
node,
rootNode,
instanceLocation,
this.evaluationPath,
walkSchema.getSchemaLocation(),
walkSchema.getSchemaNode(),
walkSchema.getParentSchema(),
this.validationContext, this.validationContext.getJsonSchemaFactory(), validationMessages
);
//@formatter:on
}
public JsonSchema getSchema() {
return this.schema;
}
@Override
public void preloadJsonSchema() {
this.schema.initializeValidators();
collectAnnotations(); // cache the flag
}
private boolean collectAnnotations() {
return hasUnevaluatedItemsValidator();
}
private boolean hasUnevaluatedItemsValidator() {
if (this.hasUnevaluatedItemsValidator == null) {
this.hasUnevaluatedItemsValidator = hasAdjacentKeywordInEvaluationPath("unevaluatedItems");
}
return hasUnevaluatedItemsValidator;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy