This library can contain breaking changes in minor
version releases.
This contains information on the notable or breaking changes in each version.
The SchemaValidatorsConfig
constructor has been deprecated. Use the SchemaValidators.builder
to create an instance instead. SchemaValidatorConfig
instances are intended to be immutable in future and those created by the builder will throw UnsupportedOperationException
when setters are called.
Note that there are differences in defaults from the builder vs the constructor.
The following builder creates the same values as the constructor previously.
SchemaValidatorsConfig config = SchemaValidatorsConfig.builder()
.pathType(PathType.LEGACY)
.errorMessageKeyword("message")
.nullableKeywordEnabled(true)
.build();
The following configurations were renamed with the old ones deprecated
handleNullableField
->nullableKeywordEnabled
openAPI3StyleDiscriminators
->discriminatorKeywordEnabled
customMessageSupported
->errorMessageKeyword
The following defaults were changed in the builder vs the constructor
pathType
fromPathType.LEGACY
toPathType.JSON_POINTER
handleNullableField
fromtrue
tofalse
customMessageSupported
fromtrue
tofalse
When using the builder custom error messages are not enabled by default and must be enabled by specifying the error message keyword to use ie. "message".
Deprecated Code | Replacement |
---|---|
SchemaValidatorsConfig config = new SchemaValidatorsConfig(); |
SchemaValidatorsConfig config = SchemaValidatorsConfig().builder().pathType(PathType.LEGACY).errorMessageKeyword("message").nullableKeywordEnabled(true).build(); |
config.setEcma262Validator(true); |
builder.regularExpressionFactory(JoniRegularExpressionFactory.getInstance()); |
config.setHandleNullableField(true); |
builder.nullableKeywordEnabled(true); |
config.setOpenAPI3StyleDiscriminators(true); |
builder.discriminatorKeywordEnabled(true); |
config.setCustomMessageSupported(true); |
builder.errorMessageKeyword("message"); |
JsonSchema.validateAndCollect
has been deprecated in favor of explicitly calling loadCollectors
.
This also deprecates the related loadCollectors
configuration in SchemaValidatorsConfig
.
This makes the CollectorContext.loadCollectors()
method public to be explicitly called instead of relying on the SchemaValidatorsConfig
.
Proper usage of the validateAndCollect
method is confusing. It relies on a configuration set in SchemaValidatorsConfig
that is configured on a per schema basis. It immediately runs loadCollectors
if set to true
and will never be able to run loadCollectors
if set to false
as the method is not public
.
The documentation has been updated to reflect the replacement, which is to explicitly create the CollectorContext
to be shared and set for each execution. Finally loadCollectors
can be called a the end if needed.
CollectorContext collectorContext = new CollectorContext();
// This adds a custom collect keyword that sets values in the CollectorContext whenever it gets processed
JsonMetaSchema metaSchema = JsonMetaSchema.builder(JsonMetaSchema.getV202012()).keyword(new CollectKeyword()).build();
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(VersionFlag.V202012, builder -> builder.metaSchema(metaSchema));
JsonSchema schema = factory.getSchema("{\n"
+ " \"collect\": true\n"
+ "}");
for (int i = 0; i < 50; i++) {
// The shared CollectorContext is set on the ExecutionContext for every run to aggregate data from all the runs
schema.validate("1", InputFormat.JSON, executionContext -> {
executionContext.setCollectorContext(collectorContext);
});
}
// This is called for Collector implementations to aggregate data
collectorContext.loadCollectors();
AtomicInteger result = (AtomicInteger) collectorContext.get("collect");
assertEquals(50, result.get());
Previously when schema $ref
are encountered, the reference and all the validators it requires will always be cached and stored if needed in the future. This can potentially cause out of memory errors for schemas that use applicators like allOf
, anyOf
, oneOf
. This can be configured by setting the cacheRefs
option to false
on SchemaValidatorsConfig.builder()
. Note that not caching will impact performance and make it slower.
This adds GraalJS as an implementation. The Joni implementation now will throw an Exception
if illegal escapes are used in the regular expressions.
The preferred way of configuring the implementation is via setting the regularExpressionFactory
on SchemaValidatorsConfig.builder()
.
Previously the if debug logging is enabled the validators will log fine grained logs. This now requires setting the debugEnabled
flag in ExecutionConfig
as the checks to determine if the logger was enabled was impacting performance.
This contains breaking changes
- to those using the walk functionality
- in how custom meta-schemas are created
When using the walker with defaults the default
across a $ref
are properly resolved and used.
The behavior for the property listener is now more consistent whether or not validation is enabled. Previously if validation is enabled but the property is null
the property listener is not called while if validation is not enabled it will be called. Now the property listener will be called in both scenarios.
The following are the breaking changes to those using the walk functionality.
WalkEvent
Field | Change | Notes |
---|---|---|
schemaLocation |
Removed | For keywords: getValidator().getSchemaLocation() . For items and properties: getSchema().getSchemaLocation() |
evaluationPath |
Removed | For keywords: getValidator().getEvaluationPath() . For items and properties: getSchema().getEvaluationPath() |
schemaNode |
Removed | getSchema().getSchemaNode() |
parentSchema |
Removed | getSchema().getParentSchema() |
schema |
New | For keywords this is the parent schema of the validator. For items and properties this is the item or property schema being evaluated. |
node |
Renamed | instanceNode |
currentJsonSchemaFactory |
Removed | getSchema().getValidationContext().getJsonSchemaFactory() |
validator |
New | The validator indicated by the keyword. |
The following are the breaking changes in how custom meta-schemas are created.
JsonSchemaFactory
- The following were renamed on
JsonSchemaFactory
builderdefaultMetaSchemaURI
->defaultMetaSchemaIri
enableUriSchemaCache
->enableSchemaCache
- The builder now accepts a
JsonMetaSchemaFactory
which can be used to restrict the loading of meta-schemas that aren't explicitly defined in theJsonSchemaFactory
. TheDisallowUnknownJsonMetaSchemaFactory
can be used to only allow explicitly configured meta-schemas.
JsonMetaSchema
- In particular
Version201909
andVersion202012
had most of the keywords moved to their respective vocabularies. - The following were renamed
getUri
->getIri
- The builder now accepts a
vocabularyFactory
to allow for custom vocabularies. - The builder now accepts a
unknownKeywordFactory
. By default this uses theUnknownKeywordFactory
implementation that logs a warning and returns aAnnotationKeyword
. TheDisallowUnknownKeywordFactory
can be used to disallow the use of unknown keywords. - The implementation of the builder now correctly throws an exception for
$vocabulary
with value oftrue
that are not known to the implementation.
ValidatorTypeCode
getNonFormatKeywords
has been removed and replaced withgetKeywords
. This now includes theformat
keyword as theJsonMetaSchema.Builder
now needs to know if theformat
keyword was configured, as it might not be in meta-schemas that don't define the format vocabulary.- The applicable
VersionCode
for each of theValidatorTypeCode
were modified to remove the keywords that are defined in vocabularies forVersion201909
andVersion202012
.
Vocabulary
- This now contains
Keyword
instances instead of the string keyword value as it needs to know the explicit implementation. For instance the implementation for theitems
keyword in Draft 2019-09 and Draft 2020-12 are different. - The following were renamed
getId
->getIri
This contains a breaking change in that the results from failFast
are no longer thrown as an exception. The single result is instead returned normally in the output. This was partially done to distinguish the fail fast result from true exceptions such as when references could not be resolved.
- Annotation collection and reporting has been implemented
- Keywords have been refactored to use annotations for evaluation to improve performance and meet functional requirements
- The list and hierarchical output formats have been implemented as per the Specification for Machine-Readable Output for JSON Schema Validation and Annotation.
- The fail fast evaluation processing has been redesigned and fixed. This currently passes the JSON Schema Test Suite with fail fast enabled. Previously contains and union type may cause incorrect results.
- This also contains fixes for regressions introduced in 1.3.0
The following keywords were refactored to improve performance and meet the functional requirements.
In particular this converts the unevaluatedItems
and unevaluatedProperties
validators to use annotations to perform the evaluation instead of the current mechanism which affects performance. This also refactors $recursiveRef
to not rely on that same mechanism.
unevaluatedProperties
unevaluatedItems
properties
patternProperties
items
/additionalItems
prefixItems
/items
contains
$recursiveRef
This also fixes the issue where the unevaluatedItems
keyword does not take into account the contains
keyword when performing the evaluation.
This also fixes cases where anyOf
short-circuits to not short-circuit the evaluation if a adjacent unevaluatedProperties
or unevaluatedItems
keyword exists.
This should fix most of the remaining functional and performance issues.
Implementations | Overall | DRAFT_03 | DRAFT_04 | DRAFT_06 | DRAFT_07 | DRAFT_2019_09 | DRAFT_2020_12 |
---|---|---|---|---|---|---|---|
NetworkNt | pass: r:4703 (100.0%) o:2369 (100.0%) fail: r:0 (0.0%) o:1 (0.0%) |
pass: r:600 (100.0%) o:251 (100.0%) fail: r:0 (0.0%) o:0 (0.0%) |
pass: r:796 (100.0%) o:318 (100.0%) fail: r:0 (0.0%) o:0 (0.0%) |
pass: r:880 (100.0%) o:541 (100.0%) fail: r:0 (0.0%) o:0 (0.0%) |
pass: r:1201 (100.0%) o:625 (100.0%) fail: r:0 (0.0%) o:0 (0.0%) |
pass: r:1226 (100.0%) o:634 (99.8%) fail: r:0 (0.0%) o:1 (0.2%) |
Benchmark Mode Cnt Score Error Units
NetworkntBenchmark.testValidate thrpt 10 6776.693 ± 115.309 ops/s
NetworkntBenchmark.testValidate:·gc.alloc.rate thrpt 10 971.191 ± 16.420 MB/sec
NetworkntBenchmark.testValidate:·gc.alloc.rate.norm thrpt 10 165318.816 ± 0.459 B/op
NetworkntBenchmark.testValidate:·gc.churn.G1_Eden_Space thrpt 10 968.894 ± 51.234 MB/sec
NetworkntBenchmark.testValidate:·gc.churn.G1_Eden_Space.norm thrpt 10 164933.962 ± 8636.203 B/op
NetworkntBenchmark.testValidate:·gc.churn.G1_Survivor_Space thrpt 10 0.002 ± 0.001 MB/sec
NetworkntBenchmark.testValidate:·gc.churn.G1_Survivor_Space.norm thrpt 10 0.274 ± 0.218 B/op
NetworkntBenchmark.testValidate:·gc.count thrpt 10 89.000 counts
NetworkntBenchmark.testValidate:·gc.time thrpt 10 99.000 ms
Benchmark Mode Cnt Score Error Units
EveritBenchmark.testValidate thrpt 10 3719.192 ± 125.592 ops/s
EveritBenchmark.testValidate:·gc.alloc.rate thrpt 10 1448.208 ± 74.746 MB/sec
EveritBenchmark.testValidate:·gc.alloc.rate.norm thrpt 10 449621.927 ± 7400.825 B/op
EveritBenchmark.testValidate:·gc.churn.G1_Eden_Space thrpt 10 1446.397 ± 79.919 MB/sec
EveritBenchmark.testValidate:·gc.churn.G1_Eden_Space.norm thrpt 10 449159.799 ± 18614.931 B/op
EveritBenchmark.testValidate:·gc.churn.G1_Survivor_Space thrpt 10 0.001 ± 0.001 MB/sec
EveritBenchmark.testValidate:·gc.churn.G1_Survivor_Space.norm thrpt 10 0.364 ± 0.391 B/op
EveritBenchmark.testValidate:·gc.count thrpt 10 133.000 counts
EveritBenchmark.testValidate:·gc.time thrpt 10 148.000 ms
This adds support for Draft 2020-12
This adds support for the following keywords
$dynamicRef
$dynamicAnchor
$vocabulary
This refactors the schema retrieval codes as the ID is based on IRI and not URI.
Note that Java does not support IRIs. See https://cr.openjdk.org/%7Edfuchs/writeups/updating-uri/ for details.
The following are removed and replaced by SchemaLoader
and SchemaMapper
.
URIFactory
- No replacement. The resolve logic is inAbsoluteIRI
.URISchemeFactory
- No replacement asURIFactory
isn't required anymore.URISchemeFetcher
- No replacement. TheSchemaLoaders
are iterated and called.URITranslator
- Replaced bySchemaMapper
.URLFactory
- No replacement asURIFactory
isn't required anymore.URLFetcher
- Replaced byUriSchemaLoader
.URNURIFactory
- No replacement asURIFactory
isn't required anymore.
The SchemaLoader
and SchemaMapper
are configured in the JsonSchemaFactory.Builder
. See Customizing Schema Retrieval.
As per the specification. The format
keyword since Draft 2019-09 no longer generates assertions by default.
This can be changed by using a custom meta schema with the relevant $vocabulary
or by setting the execution configuration to enable format assertions.
The following are a summary of the changes
- Paths are now specified using the
JsonNodePath
. The paths areinstanceLocation
,schemaLocation
andevaluationPath
. The meaning of these paths are as defined in the specification. - Schema Location comprises an absolute IRI component and a fragment that is a
JsonNodePath
that is typically a JSON pointer - Rename
at
toinstanceLocation
. Note that for therequired
validator the error messageinstanceLocation
does not point to the missing property to be consistent with the specification. TheValidationMessage
now contains aproperty
attribute if this is required. - Rename
schemaPath
toschemaLocation
. This should generally be an absolute IRI with a fragment particularly in later drafts. - Add
evaluationPath
JsonValidator
- Now contains
getSchemaLocation
andgetEvaluationPath
in the interface - Implementations now need a constructor that takes in
schemaLocation
andevaluationPath
- The
validate
method usesJsonNodePath
for theinstanceLocation
- The
validate
method with just therootNode
has been removed
JsonSchemaWalker
- The
walk
method usesJsonNodePath
for theinstanceLocation
WalkEvent
- Rename
at
toinstanceLocation
- Rename
schemaPath
toschemaLocation
- Add
evaluationPath
- Rename
keyWordName
tokeyword
WalkListenerRunner
- Rename
at
toinstanceLocation
- Rename
schemaPath
toschemaLocation
- Add
evaluationPath
BaseJsonValidator
- The
atPath
methods are removed. UseJsonNodePath.append
to get the path of the child - The
buildValidationMessage
methods are removed. Use themessage
builder method instead.
CollectorContext
- The
evaluatedProperties
andevaluatedItems
are nowCollection<JsonNodePath>
JsonSchema
- The validator keys are now using
evaluationPath
instead ofschemaPath
- The
@deprecated
constructor methods have been removed
ValidatorTypeCode
- The
customMessage
has been removed. This made theValidatorTypeCode
mutable if the feature was used as the enum is a shared instance. The logic for determining thecustomMessage
has been moved to the validator. - The creation of
newValidator
instances now uses a functional interface instead of reflection.
ValidatorState
- The
ValidatorState
is now a property of theExecutionContext
. This change is largely to improve performance. TheCollectorContext.get
method is particularly slow for this use case.
Removes use of ThreadLocal
to store context and explicitly passes the context as a parameter where needed.
The following are the main API changes, typically to accept an ExecutionContext
as a parameter
com.networknt.schema.JsonSchema
com.networknt.schema.JsonValidator
com.networknt.schema.Format
com.networknt.schema.walk.JsonSchemaWalker
com.networknt.schema.walk.WalkEvent
JsonSchema
was modified to optionally accept an ExecutionContext
for the validate
, validateAndCollect
and walk
methods. For methods where no ExecutionContext
is supplied, one is created for each run in the createExecutionContext
method in JsonSchema
.
ValidationResult
was modified to store the ExecutionContext
of the run which is also a means of reusing the context, by passing this context information from the ValidationResult
to following runs.
Up to version 1.0.81, the dependency org.apache.commons:commons-lang3
was included as a runtime dependency. Starting with 1.0.82 it is not required anymore.