All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.networknt.schema.SchemaValidatorsConfig Maven / Gradle / Ivy

There is a newer version: 1.5.3
Show newest version
/*
 * 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.networknt.schema.i18n.DefaultMessageSource;
import com.networknt.schema.i18n.MessageSource;
import com.networknt.schema.walk.DefaultItemWalkListenerRunner;
import com.networknt.schema.walk.DefaultKeywordWalkListenerRunner;
import com.networknt.schema.walk.DefaultPropertyWalkListenerRunner;
import com.networknt.schema.walk.JsonSchemaWalkListener;
import com.networknt.schema.walk.WalkListenerRunner;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;

public class SchemaValidatorsConfig {
    /**
     * Used to validate the acceptable $id values.
     */
    private JsonSchemaIdValidator schemaIdValidator = JsonSchemaIdValidator.DEFAULT;

    /**
     * when validate type, if TYPE_LOOSE = true, will try to convert string to
     * different types to match the type defined in schema.
     */
    private boolean typeLoose;

    /**
     * When set to true, validator process is stop immediately when a very first
     * validation error is discovered.
     */
    private boolean failFast;

    /**
     * When set to true, walker sets nodes that are missing or NullNode to the
     * default value, if any, and mutate the input json.
     */
    private ApplyDefaultsStrategy applyDefaultsStrategy = ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY;

    /**
     * When set to true, use ECMA-262 compatible validator
     */
    private boolean ecma262Validator;

    /**
     * When set to true, use Java-specific semantics rather than native JavaScript
     * semantics
     */
    private boolean javaSemantics;

    /**
     * When set to true, can interpret round doubles as integers
     */
    private boolean losslessNarrowing;

    /**
     * When set to true, "messages" provided in schema are used for forming validation errors
     * else default messages are used
     */
    private boolean isCustomMessageSupported = true;

    /**
     * When set to true, support for discriminators is enabled for validations of
     * oneOf, anyOf and allOf as described on GitHub.
     */
    private boolean openAPI3StyleDiscriminators = false;

    /**
     * Contains a mapping of how strict a keyword's validators should be.
     * Defaults to {@literal true}.
     * 

* Each validator has its own understanding of what constitutes strict * and permissive. */ private final Map strictness = new HashMap<>(0); /** * When a field is set as nullable in the OpenAPI specification, the schema * validator validates that it is nullable however continues with validation * against the nullable field *

* If handleNullableField is set to true && incoming field is nullable && value * is field: null --> succeed If handleNullableField is set to false && incoming * field is nullable && value is field: null --> it is up to the type validator * using the SchemaValidator to handle it. */ private boolean handleNullableField = true; /** * When set to true assumes that schema is used to validate incoming data from an API. */ private Boolean readOnly = null; /** * When set to true assumes that schema is used to to validate outgoing data from an API. */ private Boolean writeOnly = null; /** * The approach used to generate paths in reported messages, logs and errors. Default is the legacy "JSONPath-like" approach. */ private PathType pathType = PathType.DEFAULT; /** * Controls if the schema will automatically be preloaded. */ private boolean preloadJsonSchema = true; // This is just a constant for listening to all Keywords. public static final String ALL_KEYWORD_WALK_LISTENER_KEY = "com.networknt.AllKeywordWalkListener"; private final Map> keywordWalkListenersMap = new HashMap<>(); private final List propertyWalkListeners = new ArrayList<>(); private final List itemWalkListeners = new ArrayList<>(); private ExecutionContextCustomizer executionContextCustomizer; private boolean loadCollectors = true; /** * The Locale to consider when loading validation messages from the default resource bundle. */ private Locale locale; /** * The message source to use for generating localised messages. */ private MessageSource messageSource; /** * Since Draft 2019-09 format assertions are not enabled by default. */ private Boolean formatAssertionsEnabled = null; /************************ START OF UNEVALUATED CHECKS **********************************/ // These are costly in terms of performance so we provide a way to disable them. private boolean disableUnevaluatedItems = false; private boolean disableUnevaluatedProperties = false; public SchemaValidatorsConfig disableUnevaluatedAnalysis() { disableUnevaluatedItems(); disableUnevaluatedProperties(); return this; } public SchemaValidatorsConfig disableUnevaluatedItems() { this.disableUnevaluatedItems = true; return this; } public SchemaValidatorsConfig disableUnevaluatedProperties() { this.disableUnevaluatedProperties = true; return this; } public SchemaValidatorsConfig enableUnevaluatedAnalysis() { enableUnevaluatedItems(); enableUnevaluatedProperties(); return this; } public SchemaValidatorsConfig enableUnevaluatedItems() { this.disableUnevaluatedItems = false; return this; } public SchemaValidatorsConfig enableUnevaluatedProperties() { this.disableUnevaluatedProperties = false; return this; } public boolean isUnevaluatedItemsAnalysisDisabled() { return this.disableUnevaluatedItems; } public boolean isUnevaluatedItemsAnalysisEnabled() { return !isUnevaluatedItemsAnalysisDisabled(); } public boolean isUnevaluatedPropertiesAnalysisDisabled() { return this.disableUnevaluatedProperties; } public boolean isUnevaluatedPropertiesAnalysisEnabled() { return !isUnevaluatedPropertiesAnalysisDisabled(); } /************************ END OF UNEVALUATED CHECKS **********************************/ /** * * @return true if type loose is used. */ public boolean isTypeLoose() { return this.typeLoose; } public void setTypeLoose(boolean typeLoose) { this.typeLoose = typeLoose; } /** * When enabled, * {@link JsonValidator#validate(ExecutionContext, JsonNode, JsonNode, JsonNodePath)} * doesn't return any {@link java.util.Set}<{@link ValidationMessage}>, * instead a {@link JsonSchemaException} is thrown as soon as a validation * errors is discovered. * * @param failFast boolean */ public void setFailFast(final boolean failFast) { this.failFast = failFast; } public boolean isFailFast() { return this.failFast; } public void setApplyDefaultsStrategy(ApplyDefaultsStrategy applyDefaultsStrategy) { this.applyDefaultsStrategy = applyDefaultsStrategy != null ? applyDefaultsStrategy : ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY; } public ApplyDefaultsStrategy getApplyDefaultsStrategy() { return this.applyDefaultsStrategy; } public boolean isHandleNullableField() { return this.handleNullableField; } public void setHandleNullableField(boolean handleNullableField) { this.handleNullableField = handleNullableField; } public boolean isEcma262Validator() { return this.ecma262Validator; } public void setEcma262Validator(boolean ecma262Validator) { this.ecma262Validator = ecma262Validator; } public boolean isJavaSemantics() { return this.javaSemantics; } public void setJavaSemantics(boolean javaSemantics) { this.javaSemantics = javaSemantics; } public boolean isCustomMessageSupported() { return isCustomMessageSupported; } public void setCustomMessageSupported(boolean customMessageSupported) { this.isCustomMessageSupported = customMessageSupported; } public void addKeywordWalkListener(JsonSchemaWalkListener keywordWalkListener) { if (this.keywordWalkListenersMap.get(ALL_KEYWORD_WALK_LISTENER_KEY) == null) { List keywordWalkListeners = new ArrayList<>(); this.keywordWalkListenersMap.put(ALL_KEYWORD_WALK_LISTENER_KEY, keywordWalkListeners); } this.keywordWalkListenersMap.get(ALL_KEYWORD_WALK_LISTENER_KEY).add(keywordWalkListener); } public void addKeywordWalkListener(String keyword, JsonSchemaWalkListener keywordWalkListener) { if (this.keywordWalkListenersMap.get(keyword) == null) { List keywordWalkListeners = new ArrayList<>(); this.keywordWalkListenersMap.put(keyword, keywordWalkListeners); } this.keywordWalkListenersMap.get(keyword).add(keywordWalkListener); } public void addKeywordWalkListeners(List keywordWalkListeners) { if (this.keywordWalkListenersMap.get(ALL_KEYWORD_WALK_LISTENER_KEY) == null) { List ikeywordWalkListeners = new ArrayList<>(); this.keywordWalkListenersMap.put(ALL_KEYWORD_WALK_LISTENER_KEY, ikeywordWalkListeners); } this.keywordWalkListenersMap.get(ALL_KEYWORD_WALK_LISTENER_KEY).addAll(keywordWalkListeners); } public void addKeywordWalkListeners(String keyword, List keywordWalkListeners) { if (this.keywordWalkListenersMap.get(keyword) == null) { List ikeywordWalkListeners = new ArrayList<>(); this.keywordWalkListenersMap.put(keyword, ikeywordWalkListeners); } this.keywordWalkListenersMap.get(keyword).addAll(keywordWalkListeners); } public void addPropertyWalkListeners(List propertyWalkListeners) { this.propertyWalkListeners.addAll(propertyWalkListeners); } public void addPropertyWalkListener(JsonSchemaWalkListener propertyWalkListener) { this.propertyWalkListeners.add(propertyWalkListener); } public void addItemWalkListener(JsonSchemaWalkListener itemWalkListener) { this.itemWalkListeners.add(itemWalkListener); } public void addItemWalkListeners(List itemWalkListeners) { this.itemWalkListeners.addAll(itemWalkListeners); } public List getPropertyWalkListeners() { return this.propertyWalkListeners; } public Map> getKeywordWalkListenersMap() { return this.keywordWalkListenersMap; } public List getArrayItemWalkListeners() { return this.itemWalkListeners; } private final WalkListenerRunner itemWalkListenerRunner = new DefaultItemWalkListenerRunner(getArrayItemWalkListeners()); WalkListenerRunner getItemWalkListenerRunner() { return this.itemWalkListenerRunner; } private WalkListenerRunner keywordWalkListenerRunner = new DefaultKeywordWalkListenerRunner(getKeywordWalkListenersMap()); WalkListenerRunner getKeywordWalkListenerRunner() { return this.keywordWalkListenerRunner; } private WalkListenerRunner propertyWalkListenerRunner = new DefaultPropertyWalkListenerRunner(getPropertyWalkListeners()); WalkListenerRunner getPropertyWalkListenerRunner() { return this.propertyWalkListenerRunner; } public SchemaValidatorsConfig() { } public ExecutionContextCustomizer getExecutionContextCustomizer() { return this.executionContextCustomizer; } public void setExecutionContextCustomizer(ExecutionContextCustomizer executionContextCustomizer) { this.executionContextCustomizer = executionContextCustomizer; } public boolean isLosslessNarrowing() { return this.losslessNarrowing; } public void setLosslessNarrowing(boolean losslessNarrowing) { this.losslessNarrowing = losslessNarrowing; } /** * Indicates whether OpenAPI 3 style discriminators should be supported * * @return true in case discriminators are enabled * @since 1.0.51 */ public boolean isOpenAPI3StyleDiscriminators() { return this.openAPI3StyleDiscriminators; } /** * When enabled, the validation of anyOf and allOf in * polymorphism will respect OpenAPI 3 style discriminators as described in the * OpenAPI * 3.0.3 spec. The presence of a discriminator configuration on the schema * will lead to the following changes in the behavior: *

    *
  • for oneOf the spec is unfortunately very vague. Whether * oneOf semantics should be affected by discriminators or not is * not even 100% clear within the members of the OAS steering committee. * Therefore oneOf at the moment ignores discriminators
  • *
  • for anyOf the validation will choose one of the candidate * schemas for validation based on the discriminator property value and will * pass validation when this specific schema passes. This is in particular * useful when the payload could match multiple candidates in the * anyOf list and could lead to ambiguity. Example: type B has all * mandatory properties of A and adds more mandatory ones. Whether the payload * is an A or B is determined via the discriminator property name. A payload * indicating it is an instance of B then requires passing the validation of B * and passing the validation of A would not be sufficient anymore.
  • *
  • for allOf use cases with discriminators defined on the * copied-in parent type, it is possible to automatically validate against a * subtype. Example: some schema specifies that there is a field of type A. A * carries a discriminator field and B inherits from A. Then B is automatically * a candidate for validation as well and will be chosen in case the * discriminator property matches
  • *
* * @param openAPI3StyleDiscriminators whether or not discriminators should be * used. Defaults to false * @since 1.0.51 */ public void setOpenAPI3StyleDiscriminators(boolean openAPI3StyleDiscriminators) { this.openAPI3StyleDiscriminators = openAPI3StyleDiscriminators; } public void setLoadCollectors(boolean loadCollectors) { this.loadCollectors = loadCollectors; } public boolean doLoadCollectors() { return this.loadCollectors; } public boolean isReadOnly() { return null != this.readOnly && this.readOnly; } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } public boolean isWriteOnly() { return null != this.writeOnly && this.writeOnly; } public void setWriteOnly(boolean writeOnly) { this.writeOnly = writeOnly; } /** * Use {@code isReadOnly} or {@code isWriteOnly} * @return true if schema is used to write data */ @Deprecated public boolean isWriteMode() { return null == this.writeOnly || this.writeOnly; } /** * Set the approach used to generate paths in messages, logs and errors (default is PathType.LEGACY). * * @param pathType The path generation approach. */ public void setPathType(PathType pathType) { this.pathType = pathType; } /** * Get the approach used to generate paths in messages, logs and errors. * * @return The path generation approach. */ public PathType getPathType() { return this.pathType; } /** * Answers whether a keyword's validators may relax their analysis. The * default is to perform strict checking. One must explicitly allow a * validator to be more permissive. *

* Each validator has its own understanding of what is permissive and * strict. Consult the keyword's documentation for details. * * @param keyword the keyword to adjust (not null) * @return Whether to perform a strict validation. */ public boolean isStrict(String keyword) { return isStrict(keyword, Boolean.TRUE); } /** * Determines if the validator should perform strict checking. * * @param keyword the keyword * @param defaultValue the default value * @return whether to perform a strict validation */ public boolean isStrict(String keyword, Boolean defaultValue) { return this.strictness.getOrDefault(Objects.requireNonNull(keyword, "keyword cannot be null"), defaultValue); } /** * Alters the strictness of validations for a specific keyword. When set to * {@literal true}, instructs the keyword's validators to perform strict * validation. Otherwise, a validator may perform a more permissive check. * * @param keyword The keyword to adjust (not null) * @param strict Whether to perform strict validations */ public void setStrict(String keyword, boolean strict) { this.strictness.put(Objects.requireNonNull(keyword, "keyword cannot be null"), strict); } /** * Get the locale to consider when generating localised messages (default is the * JVM default). *

* This locale is on a schema basis and will be used as the default locale for * {@link com.networknt.schema.ExecutionConfig}. * * @return The locale. */ public Locale getLocale() { if (this.locale == null) { // This should not be cached as it can be changed using Locale#setDefault(Locale) return Locale.getDefault(); } return this.locale; } /** * Set the locale to consider when generating localised messages. *

* Note that this locale is set on a schema basis. To configure the schema on a * per execution basis use * {@link com.networknt.schema.ExecutionConfig#setLocale(Locale)}. * * @param locale The locale. */ public void setLocale(Locale locale) { this.locale = locale; } /** * Get the message source to use for generating localised messages. * * @return the message source */ public MessageSource getMessageSource() { if (this.messageSource == null) { return DefaultMessageSource.getInstance(); } return this.messageSource; } /** * Set the message source to use for generating localised messages. * * @param messageSource the message source */ public void setMessageSource(MessageSource messageSource) { this.messageSource = messageSource; } /** * Gets the format assertion enabled flag. *

* This defaults to null meaning that it will follow the defaults of the * specification. *

* Since draft 2019-09 this will default to false unless enabled by using the * $vocabulary keyword. * * @return the format assertions enabled flag */ public Boolean getFormatAssertionsEnabled() { return formatAssertionsEnabled; } /** * Sets the format assertion enabled flag. * * @param formatAssertionsEnabled the format assertions enabled flag */ public void setFormatAssertionsEnabled(Boolean formatAssertionsEnabled) { this.formatAssertionsEnabled = formatAssertionsEnabled; } /** * Gets the schema id validator to validate $id. * * @return the validator */ public JsonSchemaIdValidator getSchemaIdValidator() { return schemaIdValidator; } /** * Sets the schema id validator to validate $id. * * @param schemaIdValidator the validator */ public void setSchemaIdValidator(JsonSchemaIdValidator schemaIdValidator) { this.schemaIdValidator = schemaIdValidator; } /** * Gets if the schema should be preloaded. * * @return true if it should be preloaded */ public boolean isPreloadJsonSchema() { return preloadJsonSchema; } /** * Sets if the schema should be preloaded. * * @param preloadJsonSchema true to preload */ public void setPreloadJsonSchema(boolean preloadJsonSchema) { this.preloadJsonSchema = preloadJsonSchema; } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy