package schema
Contains types used by the library.
In order to simplify method signatures a series of types are defined. The types are used throughout the library.
- Source
- package.scala
- Alphabetic
- By Inheritance
- schema
- AnyRef
- Any
- Hide All
- Show All
- Public
- Protected
Type Members
- final case class Context(baseUri: URI, path: JsonPointer, schemaPath: JsonPointer, readOnly: Boolean, refs: Refs, formats: Formats) extends Product with Serializable
Contains context information as validator is executed.
Contains context information as validator is executed.
When schema validation is invoked the JSON Schema document is traversed and as the traversal occurs the JSON data is matched against the relevant constraints. The traversal of the Schema document needs to track the current base URI so it can resolve relative
$id
properties in the document itself. The paths of the current constraint and data are also maintained so that error messages can indicate the location within the data and also the location of the constraint of a failure.Other environment based information is kept to avoid passing implicit values to all validation methods. The information includes whether
readOnly
properties should be honoured and also a partial function used to validateformat
properties.Since the context is only used internally by the validation routines it is declare to be private within the project.
- baseUri
for the current JSON Schema node
- path
of the current JSON data node
- schemaPath
of the current JSON Schema node
- readOnly
true
if thereadOnly
property should be honoured- refs
map containing reference resolution entries
- formats
partial function used to validate
format
properties
- final case class EmailAddress extends Product with Serializable
Contains the local and domain parts of an email address.
Contains the local and domain parts of an email address.
The
local
part consists of the user name or group to deliver the email to on the local machine. Thedomain
part is the fully qualified machine name to which the mail is to be delivered. Both thelocal
anddomain
values are set after any escaping has been processed. Any comments in the address have been removed.For example the email address:
"fred.smith"@example.com (Fred Smith)
will result in
local
being set tofred.smith
anddomain
set toexample.com
. The comment (text enclosed in brackets) has been removed. - type Formats = PartialFunction[(String, String), Option[Error]]
Type of partial function required to handle
format
properties.Type of partial function required to handle
format
properties.The JSON Schema
format
property allows a type to be set for JSON string values. The JSON Schema Draft #7 defines a set offormat
types that should be supported. It is possible to extend this list and define your own formats by providing a partial function to handle your formats. See thewithFormats
method on SchemaValidator.The partial function takes a tuple containing the format type as a string and the value as a string. The function should return scala.None if the format validation succeeds, otherwise an Error should be returned wrapped in a Some.
- case class Hostname extends Product with Serializable
Contains a valid hostname.
Contains a valid hostname.
The definition of a valid hostname can be found in RFC 1034, section 3.1.
- See also
"RFC 1034, section 3.1"
- type Ids = Map[URI, JObject]
Type of
$$id
map maintained with a schema.Type of
$$id
map maintained with a schema.Each Schema contains a map of fully qualified
$$id
URI values and its corresponding position in the JSON Schema. The map is used when resolving
$refreferences to locate URI definitions in a schema.
- final case class Ipv4Address extends Product with Serializable
Contains an array of four numbers representing an IPv4 address.
Contains an array of four numbers representing an IPv4 address.
An IPv4 address consists of four unsigned bytes with values between 0 and 255. The bytes are represented as an array of short values as Java does not support an unsigned byte type. The array has the most significant value in index zero, with the least significant value in index three.
- final case class Ipv6Address extends Product with Serializable
Contains an IPv6 address as eight integer values.
Contains an IPv6 address as eight integer values.
An IPv6 address is of the form:
a:b:c:d:e:f:g:h
where each component is a sixteen bit number. In hex between
0
andffff
. The address is stored as an array of eight numbers where each number represents a single component.For example the address:
2001:DB8:0:0:8:800:200C:417A
would be stored as an array of eight values:
Array(0x2001, 0xD88, 0x0, 0x0, 0x8, 0x800, 0x200C, 0x417A)
- final case class JsonPointer extends Product with Serializable
Contains the components making up a JSON Pointer.
Contains the components making up a JSON Pointer.
The components that make up the path in a JSON Pointer are stored as a vector. Each component has had any escape characters replaced with the underlying character (~0 => ~, ~1 => /). A series of methods are provided that allow paths to be built and resolved.
The root path is represented by an empty JSON pointer:
JsonPointer()
Paths can be built up. For example
JsonPointer() / "items" / 0 / "name"
refers to the
name
property stored in the zeroth element of theitems
array.Paths can be resolved against a JSON document:
JsonPointer.fromString("items/0/name").resolve( parse(""" { "items": [ {"name": "spanner"}, {"name", "hammer"}, {"name", "chisel" ] }""" ) )
would resolve to the value "spanner".
- type Refs = Map[URI, Option[JValue]]
Type of
$$ref
map maintained with a schema.Type of
$$ref
map maintained with a schema.Each Schema contains a map for each fully qualified
$$ref
URI value and the position in a JSON Schema referenced by that URI. When a schema is read only local references are resolved, with external references being resolved when an external schema is resolved against the current schema. See theresolve
method on Schema. Since an reference may not be resolved its location is defined as an scala.Option. - final case class RelativeJsonPointer extends Product with Serializable
Contains the components that make up a relative JSON Pointer.
Contains the components that make up a relative JSON Pointer.
A relative JSON Pointer is defined as a non-negative integer followed by either a JSON Pointer or a
#
. The number specifies the number of parent nodes to traverse before applying either a JSON Pointer path or in the case of a#
output the current array index if in a JSON array or property key if in a JSON object.Example:
{ "foo": ["bar", "baz"], "highly": { "nested": { "objects": true } } }
Starting from the value "baz" (inside "foo"), the following JSON strings evaluate to the accompanying values:
"0" "baz" "1/0" "bar" "2/highly/nested/objects" true "0#" 1 "1#" "foo"
- type Result[A] = Validated[NonEmptyList[Error], A]
Generic type returned from validation and schema methods.
Generic type returned from validation and schema methods.
When a schema is loaded a number of errors my occur. These errors include bad URI identifiers and references. In order to allow multiple errors to be returned the Validated type is used with the error component defined as a list of Error errors. In the case of validation a list of errors is also generated and stored as a list of Error errors.
- case class Schema extends Product with Serializable
Wraps a JSON Schema compliant tree.
Wraps a JSON Schema compliant tree.
A JSON Schema tree contains the definition of a schema used to validate a JSON data structure. In order to provide efficient validation and also fast navigation of the JSON Schema tree, all
$id
properties are extracted into a map and all$ref
properties are resolved against that map where possible. Since a$ref
may refer to an external schema it may not be possible to resolve all references when wrapping the JSON Schema.The resolution of all
$ref
references is achieved by calling theresolve()
method with external JSON Schema documents. Where a reference can be resolved against the external document the entry in therefs
map is updated. Therefs
map contains as a key the fully qualified URI specified by the$ref
reference and the value points to a part of a JSON Schema resolved against the reference. If a reference has not been resolved its value is None and where resolved a Some value containing the referenced JSON Schema is found.When a JSON Schema is wrapped any internal references are resolved automatically, only external references need to added via the
resolve()
method. Consider the following three JSON Schema documents:val schema1 = parse(""" { "$id": "cdp:/test/resources/reftableone#", "definitions": { "date": { "$id": "#date", "type": "string", "format": "partial-date" } } }""" ) val schema2 = parse(""" { "$id": "cdp:/test/resources/reftabletwo#", "definitions": { "start": { "$ref":"cdp:/test/resources/reftableone#date" }, "end": { "$ref":"cdp:/test/resources/reftableone#date" } } }""" ) val schema3 = parse(""" { "$id": "cdp:/test/resources/reftablethree#", "properties": { "begin": { "$ref": "cdp:/test/resources/reftabletwo#/definitions/start" }, "finish": { "$ref": "cdp:/test/resources/reftabletwo#/definitions/end" } } }""" )
The following code is required to wrap
schema3
and resolve all references:Schema(schema1).andThen { one => Schema(schema2).andThen { two => Schema(schema3).andThen { three => three.resolve(two) .andThen(_.resolve(one)) } } }
The result of the above code is a wrapped
schema3
with all references resolved. Note the order of resolution is important.schema2
is resolved againstschema3
first (as it resolves the two references to schema2, but also introduces two new references toschema1
), thenschema1
is resolved (as it resolved the two references added byschema2
).A list of unresolved references can be retrieved via the
unresolved()
method. The method returns a list of unresolved fully qualified URI values. TheisResolved
method will returntrue
if all references have been resolved, otherwisefalse
is returned.When a JSON Schema is wrapped its root
$id
value is extracted as a property. If a root$id
URI is not specified then one is generated. The format of the generated URI is:
ni:///md5;<md5 checksum>
The
<md5 checksum>
is generated by converting the JSON Schema to a string and computing the string's md5 checksum. Such an approach ensures JSON Schema's that do not contain a root$id
URI end up with a unique root URI.
- type SchemaResult = Validated[NonEmptyList[Error], Schema]
Specific result type for loading JSON Schemas.
Specific result type for loading JSON Schemas.
When a JSON Schema is loaded either a Schema is created or a list of error is returned. This type defines the return type used when loading schemas.
- case class SchemaValidator extends Product with Serializable
Allows a JSON Schema to be used to validate a JSON data object.
Allows a JSON Schema to be used to validate a JSON data object.
A validator wraps a Schema along with the
formats
partial function to allows JSON data object to be validated. The use of a partial function for resolving different formats allows third party formats to be supported.An example use is:
val schema = parse(""" { "properties": { "foo": {"type": "integer"}, "bar": {"type": "string"} } }""" ) val validator = Schema(schema).andThen(SchemaValidator(_)) val result = validator.validate(data).isValid
It is also possible to add in extra
format
values using a partial function:private implicit val bundle = MessagesBundle("com.example.Resources") val formats: PartialFunction[(String, String), Option[Message]] = { case ("phonenumber", value) => "^[0-9]{8}$".r.findFirstIn(value) match { case None => Some(Message("BadPhoneNubmer", value)) case Some(_) => None } } val validator = Schema(schema) .andThen(SchemaValidator(_).withFormats(formats))
A standard set of formats are provided based on the JSON Schema Draft #7. In order to support formats outside the standard the
withFormats()
method should be provided with a partial function to cater for extra formats. - abstract class SchemaWalker[A] extends AnyRef
Provides a "visitor" pattern to walk a JSON Schema document.
Provides a "visitor" pattern to walk a JSON Schema document.
The
walk
method visits each node in a JSON Schema document. For each JSON Object encountered it invokes the abstractprocess
method for each property defined within the JSON object. Along with each property name and value it passes in the JSON object containing the property and the base URI for the object. The base URI is determined by processing$$id
properties found in the JSON Schema.Users should implement the abstract
process
method if they want to handle properties stored in a JSON Schema document. The method should return either an error in Error or a value defined by theA
type generic. Sinceprocess
accumulates results the typeA
must implement a Semigroup implicit value to combineA
elements.Example:
val walker = new SchemaWalker[Unit] { def process((path: JsonPointer, baseUri: URI, parent: JObject, name: String, value: JValue): Validated[Error, Unit] = (name, value) match { case ("$ref", JString(uri)) => println(s"Found reference ${baseUri.resolve(uri)}") case _ => } } walker.walk(new Uri(), parse("""{ <JSON Schema Document> }"""))
- A
type returned from
process
method
- type ValidatorResult = Validated[NonEmptyList[Error], Unit]
Specific result type for JSON validation.
Specific result type for JSON validation.
When a JSON Schema is validated against a JSON document the result is either a list of errors or
Unit
. IfUnit
is returned then the validation succeeded.
Value Members
- object Assertions
Implements all the assertions required for JSON Schema Draft #7
Implements all the assertions required for JSON Schema Draft #7
A JSON Schema document is made up of a number of assertions. The application of the assertions depends on the structure and content of the JSON data object being validated. Each assertion is implemented as a method in this object. The assertions are called from the Validator object.
Each assertion returns a ValidatorResult which contains either a Valid
Unit
value indicating the assertion was met, or an Invalid value containing a NonEmptyList of Error messages detailing why the assertion failed. - object EmailAddress extends Serializable
Creates an EmailAddress by parsing an email address string.
Creates an EmailAddress by parsing an email address string.
The parser conforms to both RFC 5322, section 3.4.1, which outlines what is a valid email address using the ASCII character set and RFC 6531 which contains extensions allowing for Unicode based email addresses.
The parser will strip out any comments (enclosed in backets) from the email address and divide the address into two parts. The first part is the
local
section which occurs before the@
symbol and the second part is thedomain
which is after the@
symbol. Any escapes are interpreted and removed from the values.- See also
"RFC 5322, section 3.4.1"
"RFC 6531"
- object Formats
Implements the standard set of string based
format
types.Implements the standard set of string based
format
types.JSON Schema Draft #7 defines a
format
property for values of type string. The format allows complex types, like date, time, etc to be checked even though the JSON value itself is still a string. Each of the required formats is available with implementations for most types.Support is not provided for:
- iri
- irireference
- uritemplate
All other required formats are implemented according to the relevant RFC. The validation of the
format
property is performed by a partial function. The type is:PartialFunction[(String, String), Option[Error]]
The input tuple consists of the format name and the value. For example:
("email", "fred.smith@axample.com")
The return value should be None if validation passes otherwise an Error wrapped in a Some indicating what was the error should be returned. The
format
method is a partial function that handles all the types defined in JSON Schema Draft #7.- See also
"JSON Schema Draft #7"
- object Hostname extends Serializable
Contains constructors to parse a hostname.
Contains constructors to parse a hostname.
A parser executes over a supplied hostname to ensure it conforms to the specifications defined in RFC 1034, section 3.1. The parser can operate in one of two modes. The first follows RFC 1034 in allowing only ASCII based names, while the second mode follows RFC 5890 which allows for Unicode based hostnames.
- object Implicits extends JsonPointerInstances with JValueInstances with NonEmptyListInstances with ErrorSyntax with JValueSyntax
Groups all implicits into a single object
Groups all implicits into a single object
Method extension implicits (Syntax suffix) and implicit variables (Instances Suffix) are mixed into a single object allowing a single import statement to be used to bring them all into scope.
The required import statement is:
import com.axiell.schema.Implicits._
- object Ipv4Address extends Serializable
Contains parser to validate an IPv4 address into four valid bytes.
Contains parser to validate an IPv4 address into four valid bytes.
The parser conforms to RFC 5890, section 2.3.2.3. The format of the IP address as a string should be:
a.b.c.d
where a, b, c, and d are numbers between 0 and 255.
- object Ipv6Address extends Serializable
Contains parser for IPv6 addresses.
Contains parser for IPv6 addresses.
The parser takes a string representing an IPv6 address and creates an Ipv6Address object if the address is valid. The address can be in any of the text forms defined in RFC 4291, section 2.2.
The three forms supported are:
- full address - all components are specified
e.g. 2001:DB8:0:0:8:800:200C:417A
- abbreviated address - use of :: for zero sequences
e.g. 2001:DB8::8:800:200C:417A
- mixed IPv4 address - use of IPv4 address for last two components
e.g. 2001:DB8::8:800:32.12.65.122
In all cases the resulting Ipv6Address object will pad out the address to its eight components.
- object JsonPointer extends Serializable
Constructs JSON Pointer objects.
Constructs JSON Pointer objects.
There are three ways to construct a JSON Pointer object. The first is to create an empty JsonPointer and use the
append
methods to add path components to the pointer.Example:
JsonPointer() / "items" / 0 / "name"
The second method is to pass individual path components to the JsonPointer constructor.
Example:
JsonPointer("items", "0", "name")
Notice the constructor only takes string components so any array index values must be provided as a string.
The third method is to provide the path as a string and have it parsed into a JsonPointer. The string must be in the escaped form, that is
~ => ~0
and/ => ~1
.Example:
JsonPointer.fromString("/items/0/name")
- object RelativeJsonPointer extends Serializable
Parses string representing a Relative JSON Pointer.
Parses string representing a Relative JSON Pointer.
The parser conforms to the draft RFC for Relative JSON Pointers. The parser is quite simple looking for a non-negative number followed by either a valid JSON Pointer or a
#
character. Any other format will fail.- See also
"https://tools.ietf.org/html/draft-handrews-relative-json-pointer-01"
- object Resolver
Resolves
$$ref
references against a given JSON Schema.Resolves
$$ref
references against a given JSON Schema.JSON Schema documents may contain
$$ref
properties. The property allows another part of a JSON Schema to be referenced from the current location. It is in essence an import or include mechanism. The value of a$$ref
property is a URI referring to a schema and a location within the schema. When a JSON Schema document is loaded the$$ref
references need to be resolved to ensure that the validation process can follow references without error.The
resolve
method performs reference resolution against a given JSON Schema. Each Schema has a table listing all references in the Schema document. The resolution routine updates that table based on the contents of a supplied schema. Such an approach allows references to external schemas to exist. To resolve such external references the resolution method must be called with the external schema. As more schemas are resolved against the references table the number of unresolved references should diminish. Once all references are resolved validation can be performed without an undefined reference error being generated. - object Schema extends Serializable
Wraps a JSON Schema document in a Schema.
Wraps a JSON Schema document in a Schema.
The wrapping process consists of three parts. The first part is the extraction of the root
$id
URI from the document. If the document does not contain a root$id
value then one is generated. The second part is the extraction of all$id
values from the document into a map containing the fully qualified version of the URI along with a link to its location in the document. The third part is the resolution of any$ref
properties in the JSON Schema document. The references are extracted into therefs
map. - object SchemaValidator extends Serializable
Create a validator for the supplied Schema.
Create a validator for the supplied Schema.
A validator is constructed suitable for validating data against the supplied JSON Schema document. The document should conform to the JSON Schema Draft #7 standard. Once a validator is constructed it can be used to validate any number of JSON data objects.
The supplied schema does not have to have all its references fully resolved, however an error will be generated if while validating an unresolved reference is encountered.
- object Validator
Validates a JSON document against a JSON Schema.
Validates a JSON document against a JSON Schema.
The validator conforms to the JSON Schema Draft #7 standard. Any validation errors are returned in a Validated as a NonEmptyList. Each element in the list is an Error containing a description of the error, the path in the JSON document where the error occurred and the path in the JSON schema document where validation failed.
The validation process is carried out by a SchemaValidator. The validation methods in this object are called by the SchemaValidator object.
Documentation for the Axiell Schema Project
Overview
The Axiell Schema Project provides a small library for validating JSON documents against a JSON Schema. The library conforms to the JSON Schema Draft #7 specification.
The library is based on a few simple principles, namely:
Package structure
The
packages consists of a number of utilities, where each utility provides a single piece of functionality. Since the library validates JSON structures two main components are provided. The first component (com.axiell.schema
) allows JSON documents conforming to the JSON Schema specification to be read. Once read a resolution process may be required to resolve any external references defined in the document.com.axiell.schema.Schema
The second component (
) takes a resolved schema and allows JSON documents to be validated against that schema. When creating a validator it is also possible to incorporate your own "format" types for validation.com.axiell.schema.SchemaValidator
A set of auxiliary components implement parsers for many of the "format" types and can be used independently of the validator itself.
Notable utilities are:
Schema
wrapper around a JSON document containing the document itself, its$id
value and resolution mappings for all$id
and$ref
directives.SchemaValidator
takes aSchema
and an optional handler for "format" types and provides a validation method for arbitrary JSON documents.Implicits
implements implicit methods and classes used to convert one class to another or pimp methods onto existing classes (e.g.same()
method toJValue
class).EmailAddress
Hostname
Ipv4Address
Ipv6Address
JsonPointer
RelativeJsonPointer
Dependencies
The list of dependencies are:
Axiell Util Library
provides error handling classes and methods that allow multilingual error messages to be generated.JSON for Scala Library
provides mthods for dealing with JSON structures. The routines work around an AST (Abstract Syntax Tree) used to represent a JSON document.Cats Functional Programming Library
provides various traits, classes and methods that simplify functional programming in Scala. Also provides theValidated
class used to return lists of validation errors.