Packages

  • package root

    Documentation for the Axiell Schema Project

    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:

    • referential transparency. Each of the methods in the library is referentially transparent, that is if the method is called with the same arguments it will always return the same value and the method does not have any side effect (e.g. update globals, change the operating environment, etc).
    • minimal functionality. The library is designed to be small incorporating a small number of dependencies. The number of methods associated with a class/object is restricted to those that provide a base level of functionality.
    • support multiple JSON libraries. It should be possible to use the library with any number of different JSON library packages (e.g json4s, jackson, etc). The current library only supports json4s, but a facade approach should be added to hide individual library implementations.
    • generic "format" implementations. The JSON Schema specification mandates a standard set of "format" types that can be used to validate string values. Each "format" type is implemented as a class with the components of the type available.
    • full error handling. Error resulting from the validation process are returned as a list of validation failures. All possible errors should be returned for a single call, eliminating the need to fix a single error and then recall a method.

    Package structure

    The com.axiell.schema 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.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.

    The second component (com.axiell.schema.SchemaValidator) 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.

    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 a Schema 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 to JValue class).
    • various auxiliary classes for handling "format" types including:

    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 the Validated class used to return lists of validation errors.
    Definition Classes
    root
  • package com
    Definition Classes
    root
  • package axiell
    Definition Classes
    com
  • package schema

    Contains types used by the library.

    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.

    Definition Classes
    axiell
  • package instances
    Definition Classes
    schema
  • package syntax
    Definition Classes
    schema
  • Assertions
  • Context
  • EmailAddress
  • Formats
  • Hostname
  • Implicits
  • Ipv4Address
  • Ipv6Address
  • JsonPointer
  • RelativeJsonPointer
  • Resolver
  • Schema
  • SchemaValidator
  • SchemaWalker
  • Validator

case class Schema extends Product with Serializable

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 the resolve() method with external JSON Schema documents. Where a reference can be resolved against the external document the entry in the refs map is updated. The refs 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 against schema3 first (as it resolves the two references to schema2, but also introduces two new references to schema1), then schema1 is resolved (as it resolved the two references added by schema2).

A list of unresolved references can be retrieved via the unresolved() method. The method returns a list of unresolved fully qualified URI values. The isResolved method will return true if all references have been resolved, otherwise false 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.

Source
Schema.scala
Linear Supertypes
Serializable, Product, Equals, AnyRef, Any
Ordering
  1. Alphabetic
  2. By Inheritance
Inherited
  1. Schema
  2. Serializable
  3. Product
  4. Equals
  5. AnyRef
  6. Any
  1. Hide All
  2. Show All
Visibility
  1. Public
  2. Protected

Value Members

  1. final def !=(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  2. final def ##(): Int
    Definition Classes
    AnyRef → Any
  3. final def ==(arg0: Any): Boolean
    Definition Classes
    AnyRef → Any
  4. final def asInstanceOf[T0]: T0
    Definition Classes
    Any
  5. def clone(): AnyRef
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.CloneNotSupportedException]) @native()
  6. final def eq(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  7. def finalize(): Unit
    Attributes
    protected[lang]
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.Throwable])
  8. final def getClass(): Class[_ <: AnyRef]
    Definition Classes
    AnyRef → Any
    Annotations
    @native()
  9. val id: URI
  10. val ids: Ids
  11. final def isInstanceOf[T0]: Boolean
    Definition Classes
    Any
  12. def isResolved: Boolean

    Indicates whether all $ref references are resolved.

    Indicates whether all $ref references are resolved.

    Searches the refs map for any unresolved references, returning false if any are found otherwise true.

    returns

    true if all $ref references resolved, otherwise false

  13. val jsonSchema: JValue
  14. final def ne(arg0: AnyRef): Boolean
    Definition Classes
    AnyRef
  15. final def notify(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  16. final def notifyAll(): Unit
    Definition Classes
    AnyRef
    Annotations
    @native()
  17. def productElementNames: Iterator[String]
    Definition Classes
    Product
  18. val refs: Refs
  19. def resolve(schema: Schema): SchemaResult

    Resolves any unresolved $ref references against the supplied schema.

    Resolves any unresolved $ref references against the supplied schema.

    Each unresolved reference in the JSON Schema is checked against the supplied Schema to see if can be resolved. Where a resolution takes place the referenced subschema is added to the refs map. If the referenced subschema contains $ref references itself these are added to the refs map and may require further resolution. The isResolved method can be used to query whether all references have been resolved.

    schema

    to search for reference resolution

    returns

    updated schema with resolved references otherwise a list of errors (normally invalid URI values for $ref properties)

  20. final def synchronized[T0](arg0: => T0): T0
    Definition Classes
    AnyRef
  21. def unresolved: List[URI]

    Generates a list of unresolved URI values.

    Generates a list of unresolved URI values.

    The refs map is searched for any unresolved references and a list of the reference's URI value is returned. The URI value is fully qualified, even for references that were specified relatively.

    returns

    list of unresolved reference URI values

  22. final def wait(): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  23. final def wait(arg0: Long, arg1: Int): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException])
  24. final def wait(arg0: Long): Unit
    Definition Classes
    AnyRef
    Annotations
    @throws(classOf[java.lang.InterruptedException]) @native()

Inherited from Serializable

Inherited from Product

Inherited from Equals

Inherited from AnyRef

Inherited from Any

Ungrouped