Resolving schemas
Every schema is uniquely identified by its URI. It is common to refer to schema definitions ($defs
) in the scope of a single schema document by using JSON pointers (e.g. #/$defs/foo
). But sometimes referencing schemas from different documents is necessary, and this can be achieved by:
Preregistering (preloading) all schema documents that might get referenced. This approach is recommended when the number of referenced schemas is either small or known in advance. It will also ensure the validity of all registered schemas early on.
Implementing SchemaResolver interface. Recommended when schemas need to be loaded dynamically and are not known in advance. Common use cases would be fetching from the web or from a file system.
There is no built-in mechanism to fetch schemas from the web — due to safety reasons, it is discouraged by specification. The only "external" schemas that will be loaded by default are the official draft meta-schemas. They are packaged with a jar and are directly read as a classpath resource.
SchemaResolver interface
It can be a simple lambda:
Please note this example is oversimplified and will cause every validation against external schema successful.
A special Result
object needs to be returned from the resolver: it is just a wrapper for a value to allow returning different types.
- Result.empty()
Means that the resolver was not able to resolve the schema (or does not support given URI). Similar to
Optional.empty()
.- Result.fromString(String rawSchema)
A result which contains a raw JSON/YAML string representing the schema.
Example:
SchemaResolver.Result.fromString("{}");- Result.fromJsonNode(JsonNode schemaNode)
A result which contains already parsed instance of
dev.harrel.jsonschemaJsonNode
representing the schema.Example:
JsonNode schemaNode = new JacksonNode.Factory().create("{}"); SchemaResolver.Result.fromJsonNode(schemaNode);- Result.fromProviderNode(Object schemaProviderNode)
A result which contains already parsed instance of provider node representing the schema. Please ensure that you are using a correct type according to your JSON/YAML provider.
Example:
Object schemaProviderNode = new ObjectMapper().readTree("{}"); SchemaResolver.Result.fromProviderNode(schemaProviderNode);
Using multiple resolvers
Let's say you have multiple ways of fetching external schemas. Instead of putting all logic combined into a single resolver, you can split the logic between multiple resolvers and then combine them:
When resolving an external schema, it will:
Invoke
ftpResolver
, ifResult.empty()
returned, go to the next step.Invoke
fileResolver
, ifResult.empty()
returned, go to the next step.Invoke
httpResolver
, ifResult.empty()
returned, go to the next step.Invoke the internal resolver which only resolves official meta-schemas. if
Result.empty()
returned, go to the next step.If it was a direct validation call reference, it will throw SchemaNotFoundException. If it was referenced via
$ref
keyword (or similar), the validation against this keyword will fail.