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

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

The newest version!
/*
 * Copyright (c) 2016 Network New Technologies Inc.
 *
 * Licensed under the Apache LicenseBuilder  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.regex.ECMAScriptRegularExpressionFactory;
import com.networknt.schema.regex.JDKRegularExpressionFactory;
import com.networknt.schema.regex.RegularExpressionFactory;
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;
import java.util.function.Consumer;

/**
 * Configuration for validators. 
 */
public class SchemaValidatorsConfig {
    // This is just a constant for listening to all Keywords.
    public static final String ALL_KEYWORD_WALK_LISTENER_KEY = "com.networknt.AllKeywordWalkListener";

    public static final int DEFAULT_PRELOAD_JSON_SCHEMA_REF_MAX_NESTING_DEPTH = 40;

    /**
     * The strategy the walker uses to 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;

    /**
     * Controls if schemas loaded from refs will be cached and reused for subsequent runs.
     */
    private boolean cacheRefs = true;

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

    private ExecutionContextCustomizer executionContextCustomizer;

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

    /**
     * Since Draft 2019-09 format assertions are not enabled by default.
     */
    private Boolean formatAssertionsEnabled = null;

    /**
     * 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 nullableKeywordEnabled = true; private final WalkListenerRunner itemWalkListenerRunner; private final List itemWalkListeners; /** * When set to true, use Java-specific semantics rather than native JavaScript * semantics */ private boolean javaSemantics; private final WalkListenerRunner keywordWalkListenerRunner; private final Map> keywordWalkListenersMap; /** * The Locale to consider when loading validation messages from the default resource bundle. */ private Locale locale; /** * When set to true, can interpret round doubles as integers */ private boolean losslessNarrowing; /** * The message source to use for generating localised messages. */ private MessageSource messageSource; /** * When set to true, support for discriminators is enabled for validations of * oneOf, anyOf and allOf as described on GitHub. */ private boolean discriminatorKeywordEnabled = false; /** * 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; /** * Controls the max depth of the evaluation path to preload when preloading refs. */ private int preloadJsonSchemaRefMaxNestingDepth = DEFAULT_PRELOAD_JSON_SCHEMA_REF_MAX_NESTING_DEPTH; private final WalkListenerRunner propertyWalkListenerRunner; private final List propertyWalkListeners; /** * When set to true assumes that schema is used to validate incoming data from an API. */ private Boolean readOnly = null; /** * Used to create {@link com.networknt.schema.regex.RegularExpression}. */ private RegularExpressionFactory regularExpressionFactory = JDKRegularExpressionFactory.getInstance(); /** * Used to validate the acceptable $id values. */ private JsonSchemaIdValidator schemaIdValidator = JsonSchemaIdValidator.DEFAULT; /** * 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; /** * 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 assumes that schema is used to validate outgoing data from an API. */ private Boolean writeOnly = null; /** * Constructor to create an instance. *

* This is deprecated in favor of using the builder * {@link SchemaValidatorsConfig#builder()} to create an instance. Migration * note: The builder has different defaults from the constructor. *

     * SchemaValidatorsConfig config = SchemaValidatorsConfig.builder()
     *     .pathType(PathType.LEGACY)
     *     .errorMessageKeyword("message")
     *     .nullableKeywordEnabled(true)
     *     .build();
     * 
*
    *
  • customMessageSupported (errorMessageKeyword): change from message to null *
  • pathType: changed from PathType.LEGACY to PathType.JSON_POINTER. *
  • handleNullableField (nullableKeywordEnabled): changed from true to false *
*/ @Deprecated public SchemaValidatorsConfig() { this.strictness = new HashMap<>(0); this.keywordWalkListenersMap = new HashMap<>(); this.propertyWalkListeners = new ArrayList<>(); this.itemWalkListeners = new ArrayList<>(); this.itemWalkListenerRunner = new DefaultItemWalkListenerRunner(getArrayItemWalkListeners()); this.keywordWalkListenerRunner = new DefaultKeywordWalkListenerRunner(getKeywordWalkListenersMap()); this.propertyWalkListenerRunner = new DefaultPropertyWalkListenerRunner(getPropertyWalkListeners()); } SchemaValidatorsConfig(ApplyDefaultsStrategy applyDefaultsStrategy, boolean cacheRefs, String errorMessageKeyword, ExecutionContextCustomizer executionContextCustomizer, boolean failFast, Boolean formatAssertionsEnabled, boolean nullableKeywordEnabled, List itemWalkListeners, boolean javaSemantics, Map> keywordWalkListenersMap, Locale locale, boolean losslessNarrowing, MessageSource messageSource, boolean discriminatorKeywordEnabled, PathType pathType, boolean preloadJsonSchema, int preloadJsonSchemaRefMaxNestingDepth, List propertyWalkListeners, Boolean readOnly, RegularExpressionFactory regularExpressionFactory, JsonSchemaIdValidator schemaIdValidator, Map strictness, boolean typeLoose, Boolean writeOnly) { super(); this.applyDefaultsStrategy = applyDefaultsStrategy; this.cacheRefs = cacheRefs; this.errorMessageKeyword = errorMessageKeyword; this.executionContextCustomizer = executionContextCustomizer; this.failFast = failFast; this.formatAssertionsEnabled = formatAssertionsEnabled; this.nullableKeywordEnabled = nullableKeywordEnabled; this.itemWalkListeners = itemWalkListeners; this.javaSemantics = javaSemantics; this.keywordWalkListenersMap = keywordWalkListenersMap; this.locale = locale; this.losslessNarrowing = losslessNarrowing; this.messageSource = messageSource; this.discriminatorKeywordEnabled = discriminatorKeywordEnabled; this.pathType = pathType; this.preloadJsonSchema = preloadJsonSchema; this.preloadJsonSchemaRefMaxNestingDepth = preloadJsonSchemaRefMaxNestingDepth; this.propertyWalkListeners = propertyWalkListeners; this.readOnly = readOnly; this.regularExpressionFactory = regularExpressionFactory; this.schemaIdValidator = schemaIdValidator; this.strictness = strictness; this.typeLoose = typeLoose; this.writeOnly = writeOnly; this.itemWalkListenerRunner = new DefaultItemWalkListenerRunner(getArrayItemWalkListeners()); this.keywordWalkListenerRunner = new DefaultKeywordWalkListenerRunner(getKeywordWalkListenersMap()); this.propertyWalkListenerRunner = new DefaultPropertyWalkListenerRunner(getPropertyWalkListeners()); } public void addItemWalkListener(JsonSchemaWalkListener itemWalkListener) { this.itemWalkListeners.add(itemWalkListener); } public void addItemWalkListeners(List itemWalkListeners) { this.itemWalkListeners.addAll(itemWalkListeners); } 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 addPropertyWalkListener(JsonSchemaWalkListener propertyWalkListener) { this.propertyWalkListeners.add(propertyWalkListener); } public void addPropertyWalkListeners(List propertyWalkListeners) { this.propertyWalkListeners.addAll(propertyWalkListeners); } public ApplyDefaultsStrategy getApplyDefaultsStrategy() { return this.applyDefaultsStrategy; } public List getArrayItemWalkListeners() { return this.itemWalkListeners; } public ExecutionContextCustomizer getExecutionContextCustomizer() { return this.executionContextCustomizer; } /** * 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; } WalkListenerRunner getItemWalkListenerRunner() { return this.itemWalkListenerRunner; } WalkListenerRunner getKeywordWalkListenerRunner() { return this.keywordWalkListenerRunner; } public Map> getKeywordWalkListenersMap() { return this.keywordWalkListenersMap; } /** * 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; } /** * 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; } /** * Get the approach used to generate paths in messages, logs and errors. * * @return The path generation approach. */ public PathType getPathType() { return this.pathType; } /** * Gets the max depth of the evaluation path to preload when preloading refs. * * @return the max depth to preload */ public int getPreloadJsonSchemaRefMaxNestingDepth() { return preloadJsonSchemaRefMaxNestingDepth; } WalkListenerRunner getPropertyWalkListenerRunner() { return this.propertyWalkListenerRunner; } public List getPropertyWalkListeners() { return this.propertyWalkListeners; } /** * Gets the regular expression factory. *

* This defaults to the JDKRegularExpressionFactory and the implementations * require inclusion of optional org.jruby.joni:joni or org.graalvm.js:js dependencies. * * @return the factory */ public RegularExpressionFactory getRegularExpressionFactory() { return regularExpressionFactory; } /** * Gets the schema id validator to validate $id. * * @return the validator */ public JsonSchemaIdValidator getSchemaIdValidator() { return schemaIdValidator; } /** * Gets if schemas loaded from refs will be cached and reused for subsequent * runs. * * @return true if schemas loaded from refs should be cached */ public boolean isCacheRefs() { return cacheRefs; } @Deprecated public boolean isCustomMessageSupported() { return this.errorMessageKeyword != null; } public String getErrorMessageKeyword() { return this.errorMessageKeyword; } /** * Gets whether to use a ECMA-262 compliant regular expression validator. *

* This defaults to the false and setting true require inclusion of optional * org.jruby.joni:joni or org.graalvm.js:js dependencies. * * @return true if ECMA-262 compliant */ public boolean isEcma262Validator() { return !(this.regularExpressionFactory instanceof JDKRegularExpressionFactory); } public boolean isFailFast() { return this.failFast; } /** * Deprecated use {{@link #isNullableKeywordEnabled()} instead. * * @return true if the nullable keyword is enabled */ @Deprecated public boolean isHandleNullableField() { return isNullableKeywordEnabled(); } /** * Gets if the nullable keyword is enabled. * * @return true if the nullable keyword is enabled */ public boolean isNullableKeywordEnabled() { return this.nullableKeywordEnabled; } public boolean isJavaSemantics() { return this.javaSemantics; } public boolean isLosslessNarrowing() { return this.losslessNarrowing; } /** * Indicates whether OpenAPI 3 style discriminators should be supported *

* Deprecated use {{@link #isDiscriminatorKeywordEnabled()} instead. * * @return true in case discriminators are enabled * @since 1.0.51 */ @Deprecated public boolean isOpenAPI3StyleDiscriminators() { return isDiscriminatorKeywordEnabled(); } /** * Gets if the discriminator keyword is enabled. * * @return true if the discriminator keyword is enabled */ public boolean isDiscriminatorKeywordEnabled() { return this.discriminatorKeywordEnabled; } /** * Gets if the schema should be preloaded. * * @return true if it should be preloaded */ public boolean isPreloadJsonSchema() { return preloadJsonSchema; } public boolean isReadOnly() { return null != this.readOnly && this.readOnly; } /** * 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); } /** * * @return true if type loose is used. */ public boolean isTypeLoose() { return this.typeLoose; } public boolean isWriteOnly() { return null != this.writeOnly && this.writeOnly; } public void setApplyDefaultsStrategy(ApplyDefaultsStrategy applyDefaultsStrategy) { this.applyDefaultsStrategy = applyDefaultsStrategy != null ? applyDefaultsStrategy : ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY; } /** * Sets if schemas loaded from refs will be cached and reused for subsequent * runs. *

* Note that setting this to false will affect performance as refs will need to * be repeatedly resolved for each evaluation run. It may be needed to be set to * false if there are multiple nested applicators like anyOf, oneOf and allOf as * that will consume a lot of memory to cache all the permutations. * * @param cacheRefs true to cache */ public void setCacheRefs(boolean cacheRefs) { this.cacheRefs = cacheRefs; } /** * Sets whether custom error messages in the schema are used. *

* This is deprecated in favor of setting the error message keyword to use. * * @param customMessageSupported true to use message as the error message keyword */ @Deprecated public void setCustomMessageSupported(boolean customMessageSupported) { this.errorMessageKeyword = customMessageSupported ? "message" : null; } /** * Sets whether to use a ECMA-262 compliant regular expression validator. *

* This defaults to the false and setting true require inclusion of optional * org.jruby.joni:joni or org.graalvm.js:js dependencies. * * @param ecma262Validator true if ECMA-262 compliant */ public void setEcma262Validator(boolean ecma262Validator) { this.regularExpressionFactory = ecma262Validator ? ECMAScriptRegularExpressionFactory.getInstance() : JDKRegularExpressionFactory.getInstance(); } public void setExecutionContextCustomizer(ExecutionContextCustomizer executionContextCustomizer) { this.executionContextCustomizer = executionContextCustomizer; } /** * 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; } /** * Sets the format assertion enabled flag. *

* This is deprecated. Either set this using the builder * SchemaValidatorsConfig.builder().formatAssertionsEnabled(true).build() or * this should be set via * executionContext.getExecutionConfig().setFormatAssertionsEnabled(true). * * @param formatAssertionsEnabled the format assertions enabled flag */ @Deprecated public void setFormatAssertionsEnabled(Boolean formatAssertionsEnabled) { this.formatAssertionsEnabled = formatAssertionsEnabled; } public void setHandleNullableField(boolean handleNullableField) { this.nullableKeywordEnabled = handleNullableField; } public void setJavaSemantics(boolean javaSemantics) { this.javaSemantics = javaSemantics; } /** * 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)}. *

* This is deprecated. Either set this using the builder * SchemaValidatorsConfig.builder().locale(locale).build() or this should be set * via executionContext.getExecutionConfig().setLocale(locale). * * @param locale The locale. */ @Deprecated public void setLocale(Locale locale) { this.locale = locale; } public void setLosslessNarrowing(boolean losslessNarrowing) { this.losslessNarrowing = losslessNarrowing; } /** * Set the message source to use for generating localised messages. * * @param messageSource the message source */ public void setMessageSource(MessageSource messageSource) { this.messageSource = messageSource; } /** * 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 discriminators should be used. * Defaults to false * @since 1.0.51 */ public void setOpenAPI3StyleDiscriminators(boolean openAPI3StyleDiscriminators) { this.discriminatorKeywordEnabled = openAPI3StyleDiscriminators; } /** * 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; } /** * Sets if the schema should be preloaded. * * @param preloadJsonSchema true to preload */ public void setPreloadJsonSchema(boolean preloadJsonSchema) { this.preloadJsonSchema = preloadJsonSchema; } /** * Sets the max depth of the evaluation path to preload when preloading refs. * * @param preloadJsonSchemaRefMaxNestingDepth the max depth to preload */ public void setPreloadJsonSchemaRefMaxNestingDepth(int preloadJsonSchemaRefMaxNestingDepth) { this.preloadJsonSchemaRefMaxNestingDepth = preloadJsonSchemaRefMaxNestingDepth; } public void setReadOnly(boolean readOnly) { this.readOnly = readOnly; } /** * Sets the regular expression factory. *

* This defaults to the JDKRegularExpressionFactory and the implementations * require inclusion of optional org.jruby.joni:joni or org.graalvm.js:js dependencies. * * @see JDKRegularExpressionFactory * @see ECMAScriptRegularExpressionFactory * @param regularExpressionFactory the factory */ public void setRegularExpressionFactory(RegularExpressionFactory regularExpressionFactory) { this.regularExpressionFactory = regularExpressionFactory; } /** * Sets the schema id validator to validate $id. * * @param schemaIdValidator the validator */ public void setSchemaIdValidator(JsonSchemaIdValidator schemaIdValidator) { this.schemaIdValidator = schemaIdValidator; } /** * 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); } public void setTypeLoose(boolean typeLoose) { this.typeLoose = typeLoose; } public void setWriteOnly(boolean writeOnly) { this.writeOnly = writeOnly; } public static Builder builder() { return new Builder(); } public static Builder builder(SchemaValidatorsConfig config) { Builder builder = new Builder(); builder.applyDefaultsStrategy = config.applyDefaultsStrategy; builder.cacheRefs = config.cacheRefs; builder.errorMessageKeyword = config.errorMessageKeyword; builder.executionContextCustomizer = config.executionContextCustomizer; builder.failFast = config.failFast; builder.formatAssertionsEnabled = config.formatAssertionsEnabled; builder.nullableKeywordEnabled = config.nullableKeywordEnabled; builder.itemWalkListeners = config.itemWalkListeners; builder.javaSemantics = config.javaSemantics; builder.keywordWalkListeners = config.keywordWalkListenersMap; builder.locale = config.locale; builder.losslessNarrowing = config.losslessNarrowing; builder.messageSource = config.messageSource; builder.discriminatorKeywordEnabled = config.discriminatorKeywordEnabled; builder.pathType = config.pathType; builder.preloadJsonSchema = config.preloadJsonSchema; builder.preloadJsonSchemaRefMaxNestingDepth = config.preloadJsonSchemaRefMaxNestingDepth; builder.propertyWalkListeners = config.propertyWalkListeners; builder.readOnly = config.readOnly; builder.regularExpressionFactory = config.regularExpressionFactory; builder.schemaIdValidator = config.schemaIdValidator; builder.strictness = config.strictness; builder.typeLoose = config.typeLoose; builder.writeOnly = config.writeOnly; return builder; } /** * Builder for {@link SchemaValidatorsConfig}. */ public static class Builder { private ApplyDefaultsStrategy applyDefaultsStrategy = ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY; private boolean cacheRefs = true; private String errorMessageKeyword = null; private ExecutionContextCustomizer executionContextCustomizer = null; private boolean failFast = false; private Boolean formatAssertionsEnabled = false; private boolean nullableKeywordEnabled = false; private List itemWalkListeners = new ArrayList<>(); private boolean javaSemantics = false; private Map> keywordWalkListeners = new HashMap<>(); private Locale locale = null; // This must be null to use Locale.getDefault() as the default can be changed private boolean losslessNarrowing = false; private MessageSource messageSource = null; private boolean discriminatorKeywordEnabled = false; private PathType pathType = PathType.JSON_POINTER; private boolean preloadJsonSchema = true; private int preloadJsonSchemaRefMaxNestingDepth = DEFAULT_PRELOAD_JSON_SCHEMA_REF_MAX_NESTING_DEPTH; private List propertyWalkListeners = new ArrayList<>(); private Boolean readOnly = null; private RegularExpressionFactory regularExpressionFactory = JDKRegularExpressionFactory.getInstance(); private JsonSchemaIdValidator schemaIdValidator = JsonSchemaIdValidator.DEFAULT; private Map strictness = new HashMap<>(0); private boolean typeLoose = false; private Boolean writeOnly = null; /** * Sets the strategy the walker uses to sets nodes to the default value. *

* Defaults to {@link ApplyDefaultsStrategy#EMPTY_APPLY_DEFAULTS_STRATEGY}. * * @param applyDefaultsStrategy the strategy * @return the builder */ public Builder applyDefaultsStrategy(ApplyDefaultsStrategy applyDefaultsStrategy) { this.applyDefaultsStrategy = applyDefaultsStrategy != null ? applyDefaultsStrategy : ApplyDefaultsStrategy.EMPTY_APPLY_DEFAULTS_STRATEGY; return this; } /** * Sets if schemas loaded from refs will be cached and reused for subsequent runs. *

* Defaults to true. * * @param cacheRefs true to cache * @return the builder */ public Builder cacheRefs(boolean cacheRefs) { this.cacheRefs = cacheRefs; return this; } /** * Sets the error message keyword for setting custom messages in the schema. *

* Defaults to null meaning custom messages are not enabled. * * @param errorMessageKeyword to use for custom messages in the schema * @return the builder */ public Builder errorMessageKeyword(String errorMessageKeyword) { this.errorMessageKeyword = errorMessageKeyword; return this; } /** * Sets the execution context customizer that is run before each run. * * @param executionContextCustomizer the customizer * @return the builder */ public Builder executionContextCustomizer(ExecutionContextCustomizer executionContextCustomizer) { this.executionContextCustomizer = executionContextCustomizer; return this; } /** * Sets if the validation should immediately return once a validation error has * occurred. This can improve performance if inputs are invalid but cannot * return all error messages to the caller. *

* Defaults to false. * * @param failFast true to enable * @return the builder */ public Builder failFast(boolean failFast) { this.failFast = failFast; return this; } /** * Sets if format assertions are enabled. If format assertions are not enabled * the format keyword will behave like an annotation and not attempt to validate * if the inputs are valid. *

* Defaults to not enabling format assertions for Draft 2019-09 and above and * enabling format assertions for Draft 7 and below. * * @param formatAssertionsEnabled true to enable * @return the builder */ public Builder formatAssertionsEnabled(Boolean formatAssertionsEnabled) { this.formatAssertionsEnabled = formatAssertionsEnabled; return this; } /** * Sets if the nullable keyword is enabled. * * @param nullableKeywordEnabled true to enable * @return the builder */ public Builder nullableKeywordEnabled(boolean nullableKeywordEnabled) { this.nullableKeywordEnabled = nullableKeywordEnabled; return this; } public Builder itemWalkListeners(List itemWalkListeners) { this.itemWalkListeners = itemWalkListeners; return this; } public Builder javaSemantics(boolean javaSemantics) { this.javaSemantics = javaSemantics; return this; } public Builder keywordWalkListeners(Map> keywordWalkListeners) { this.keywordWalkListeners = keywordWalkListeners; return this; } /** * 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)}. *

* Defaults to use {@link Locale#getDefault()}. * * @param locale The locale. * @return the builder */ public Builder locale(Locale locale) { this.locale = locale; return this; } public Builder losslessNarrowing(boolean losslessNarrowing) { this.losslessNarrowing = losslessNarrowing; return this; } /** * Sets the message source to use for generating localised messages. * * @param messageSource the message source * @return the builder */ public Builder messageSource(MessageSource messageSource) { this.messageSource = messageSource; return this; } /** * Sets if the discriminator keyword is enabled. *

* Defaults to false. * * @param discriminatorKeywordEnabled true to enable * @return the builder */ public Builder discriminatorKeywordEnabled(boolean discriminatorKeywordEnabled) { this.discriminatorKeywordEnabled = discriminatorKeywordEnabled; return this; } /** * Sets the path type to use when reporting the instance location of errors. *

* Defaults to {@link PathType#JSON_POINTER}. * * @param pathType the path type * @return the path type */ public Builder pathType(PathType pathType) { this.pathType = pathType; return this; } /** * Sets if the schema should be preloaded. *

* Defaults to true. * * @param preloadJsonSchema true to preload * @return the builder */ public Builder preloadJsonSchema(boolean preloadJsonSchema) { this.preloadJsonSchema = preloadJsonSchema; return this; } /** * Sets the max depth of the evaluation path to preload when preloading refs. *

* Defaults to 40. * * @param preloadJsonSchemaRefMaxNestingDepth to preload * @return the builder */ public Builder preloadJsonSchemaRefMaxNestingDepth(int preloadJsonSchemaRefMaxNestingDepth) { this.preloadJsonSchemaRefMaxNestingDepth = preloadJsonSchemaRefMaxNestingDepth; return this; } public Builder propertyWalkListeners(List propertyWalkListeners) { this.propertyWalkListeners = propertyWalkListeners; return this; } public Builder readOnly(Boolean readOnly) { this.readOnly = readOnly; return this; } /** * Sets the regular expression factory. *

* Defaults to the {@link JDKRegularExpressionFactory} *

* The {@link ECMAScriptRegularExpressionFactory} requires the inclusion of * optional org.jruby.joni:joni or org.graalvm.js:js dependencies. * * @see JDKRegularExpressionFactory * @see ECMAScriptRegularExpressionFactory * @param regularExpressionFactory the factory * @return the builder */ public Builder regularExpressionFactory(RegularExpressionFactory regularExpressionFactory) { this.regularExpressionFactory = regularExpressionFactory; return this; } /** * Sets the schema id validator to use. *

* Defaults to {@link JsonSchemaIdValidator#DEFAULT}. * * @param schemaIdValidator the builder * @return the builder */ public Builder schemaIdValidator(JsonSchemaIdValidator schemaIdValidator) { this.schemaIdValidator = schemaIdValidator; return this; } public Builder strict(Map strict) { this.strictness = strict; return this; } public Builder typeLoose(boolean typeLoose) { this.typeLoose = typeLoose; return this; } public Builder writeOnly(Boolean writeOnly) { this.writeOnly = writeOnly; return this; } public SchemaValidatorsConfig build() { return new ImmutableSchemaValidatorsConfig(applyDefaultsStrategy, cacheRefs, errorMessageKeyword, executionContextCustomizer, failFast, formatAssertionsEnabled, nullableKeywordEnabled, itemWalkListeners, javaSemantics, keywordWalkListeners, locale, losslessNarrowing, messageSource, discriminatorKeywordEnabled, pathType, preloadJsonSchema, preloadJsonSchemaRefMaxNestingDepth, propertyWalkListeners, readOnly, regularExpressionFactory, schemaIdValidator, strictness, typeLoose, writeOnly); } public Builder strict(String keyword, boolean strict) { this.strictness.put(Objects.requireNonNull(keyword, "keyword cannot be null"), strict); return this; } public Builder keywordWalkListener(String keyword, JsonSchemaWalkListener keywordWalkListener) { this.keywordWalkListeners.computeIfAbsent(keyword, key -> new ArrayList<>()).add(keywordWalkListener); return this; } public Builder keywordWalkListener(JsonSchemaWalkListener keywordWalkListener) { return keywordWalkListener(ALL_KEYWORD_WALK_LISTENER_KEY, keywordWalkListener); } public Builder keywordWalkListeners(Consumer>> keywordWalkListeners) { keywordWalkListeners.accept(this.keywordWalkListeners); return this; } public Builder propertyWalkListener(JsonSchemaWalkListener propertyWalkListener) { this.propertyWalkListeners.add(propertyWalkListener); return this; } public Builder propertyWalkListeners(Consumer> propertyWalkListeners) { propertyWalkListeners.accept(this.propertyWalkListeners); return this; } public Builder itemWalkListener(JsonSchemaWalkListener itemWalkListener) { this.itemWalkListeners.add(itemWalkListener); return this; } public Builder itemWalkListeners(Consumer> itemWalkListeners) { itemWalkListeners.accept(this.itemWalkListeners); return this; } } /** * {@link SchemaValidatorsConfig} that throws on mutators or deprecated methods. *

* The {@link SchemaValidatorsConfig} will be made immutable in a future breaking release. */ public static class ImmutableSchemaValidatorsConfig extends SchemaValidatorsConfig { public ImmutableSchemaValidatorsConfig(ApplyDefaultsStrategy applyDefaultsStrategy, boolean cacheRefs, String errorMessageKeyword, ExecutionContextCustomizer executionContextCustomizer, boolean failFast, Boolean formatAssertionsEnabled, boolean handleNullableField, List itemWalkListeners, boolean javaSemantics, Map> keywordWalkListenersMap, Locale locale, boolean losslessNarrowing, MessageSource messageSource, boolean openAPI3StyleDiscriminators, PathType pathType, boolean preloadJsonSchema, int preloadJsonSchemaRefMaxNestingDepth, List propertyWalkListeners, Boolean readOnly, RegularExpressionFactory regularExpressionFactory, JsonSchemaIdValidator schemaIdValidator, Map strictness, boolean typeLoose, Boolean writeOnly) { super(applyDefaultsStrategy, cacheRefs, errorMessageKeyword, executionContextCustomizer, failFast, formatAssertionsEnabled, handleNullableField, itemWalkListeners, javaSemantics, keywordWalkListenersMap, locale, losslessNarrowing, messageSource, openAPI3StyleDiscriminators, pathType, preloadJsonSchema, preloadJsonSchemaRefMaxNestingDepth, propertyWalkListeners, readOnly, regularExpressionFactory, schemaIdValidator, strictness, typeLoose, writeOnly); } @Override public void addItemWalkListener(JsonSchemaWalkListener itemWalkListener) { throw new UnsupportedOperationException(); } @Override public void addItemWalkListeners(List itemWalkListeners) { throw new UnsupportedOperationException(); } @Override public void addKeywordWalkListener(JsonSchemaWalkListener keywordWalkListener) { throw new UnsupportedOperationException(); } @Override public void addKeywordWalkListener(String keyword, JsonSchemaWalkListener keywordWalkListener) { throw new UnsupportedOperationException(); } @Override public void addKeywordWalkListeners(List keywordWalkListeners) { throw new UnsupportedOperationException(); } @Override public void addKeywordWalkListeners(String keyword, List keywordWalkListeners) { throw new UnsupportedOperationException(); } @Override public void addPropertyWalkListener(JsonSchemaWalkListener propertyWalkListener) { throw new UnsupportedOperationException(); } @Override public void addPropertyWalkListeners(List propertyWalkListeners) { throw new UnsupportedOperationException(); } @Override public void setApplyDefaultsStrategy(ApplyDefaultsStrategy applyDefaultsStrategy) { throw new UnsupportedOperationException(); } @Override public void setCacheRefs(boolean cacheRefs) { throw new UnsupportedOperationException(); } @Override public void setCustomMessageSupported(boolean customMessageSupported) { throw new UnsupportedOperationException(); } @Override public void setEcma262Validator(boolean ecma262Validator) { throw new UnsupportedOperationException(); } @Override public void setExecutionContextCustomizer(ExecutionContextCustomizer executionContextCustomizer) { throw new UnsupportedOperationException(); } @Override public void setFailFast(boolean failFast) { throw new UnsupportedOperationException(); } @Override public void setFormatAssertionsEnabled(Boolean formatAssertionsEnabled) { throw new UnsupportedOperationException(); } @Override public void setHandleNullableField(boolean handleNullableField) { throw new UnsupportedOperationException(); } @Override public void setJavaSemantics(boolean javaSemantics) { throw new UnsupportedOperationException(); } @Override public void setLocale(Locale locale) { throw new UnsupportedOperationException(); } @Override public void setLosslessNarrowing(boolean losslessNarrowing) { throw new UnsupportedOperationException(); } @Override public void setMessageSource(MessageSource messageSource) { throw new UnsupportedOperationException(); } @Override public void setOpenAPI3StyleDiscriminators(boolean openAPI3StyleDiscriminators) { throw new UnsupportedOperationException(); } @Override public void setPathType(PathType pathType) { throw new UnsupportedOperationException(); } @Override public void setPreloadJsonSchema(boolean preloadJsonSchema) { throw new UnsupportedOperationException(); } @Override public void setPreloadJsonSchemaRefMaxNestingDepth(int preloadJsonSchemaRefMaxNestingDepth) { throw new UnsupportedOperationException(); } @Override public void setReadOnly(boolean readOnly) { throw new UnsupportedOperationException(); } @Override public void setRegularExpressionFactory(RegularExpressionFactory regularExpressionFactory) { throw new UnsupportedOperationException(); } @Override public void setSchemaIdValidator(JsonSchemaIdValidator schemaIdValidator) { throw new UnsupportedOperationException(); } @Override public void setStrict(String keyword, boolean strict) { throw new UnsupportedOperationException(); } @Override public void setTypeLoose(boolean typeLoose) { throw new UnsupportedOperationException(); } @Override public void setWriteOnly(boolean writeOnly) { throw new UnsupportedOperationException(); } @Override public void setLoadCollectors(boolean loadCollectors) { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig disableUnevaluatedAnalysis() { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig disableUnevaluatedItems() { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig disableUnevaluatedProperties() { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig enableUnevaluatedAnalysis() { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig enableUnevaluatedItems() { throw new UnsupportedOperationException(); } @Override public SchemaValidatorsConfig enableUnevaluatedProperties() { throw new UnsupportedOperationException(); } } /* Below are deprecated for removal */ @Deprecated private boolean loadCollectors = true; /** * 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; } /** * Sets if collectors are to be loaded. *

* This is deprecated in favor of the caller calling {@link CollectorContext#loadCollectors()} manually. * * @param loadCollectors to load collectors */ @Deprecated public void setLoadCollectors(boolean loadCollectors) { this.loadCollectors = loadCollectors; } /** * Gets if collectors are to be loaded. * * @return if collectors are to be loader */ @Deprecated public boolean doLoadCollectors() { return this.loadCollectors; } @Deprecated public SchemaValidatorsConfig disableUnevaluatedAnalysis() { return this; } @Deprecated public SchemaValidatorsConfig disableUnevaluatedItems() { return this; } @Deprecated public SchemaValidatorsConfig disableUnevaluatedProperties() { return this; } @Deprecated public SchemaValidatorsConfig enableUnevaluatedAnalysis() { return this; } @Deprecated public SchemaValidatorsConfig enableUnevaluatedItems() { return this; } @Deprecated public SchemaValidatorsConfig enableUnevaluatedProperties() { return this; } @Deprecated public boolean isUnevaluatedItemsAnalysisDisabled() { return false; } @Deprecated public boolean isUnevaluatedItemsAnalysisEnabled() { return !isUnevaluatedItemsAnalysisDisabled(); } @Deprecated public boolean isUnevaluatedPropertiesAnalysisDisabled() { return false; } @Deprecated public boolean isUnevaluatedPropertiesAnalysisEnabled() { return !isUnevaluatedPropertiesAnalysisDisabled(); } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy