JSON Schema is a specification for defining the structure of JSON data. JSON Schema provides the definition of contractual type constraints for describing a valid set of values for object style data structures. JSON Schema development is based on the concepts from XML Schema, RelaxNG, and Kwalify, but is a JSON-based format, so it is well suited for JSON-based applications. It is intended to provide validation, documentation, and interaction control. Defining type constraints provides a standardized form of data documentation that can be used for data persistence, form generation, and creating contracts on data used in web services.

Dojo 1.2 now includes a JSON Schema validator module, dojox.json.schema, under the dojox.json project (which also includes JSON Referencing and JSONQuery). The validator can be used to determine if an instance object or value is valid against a given schema. Using the validator is very straightforward:

dojo.require("dojox.json.schema");
schema = {
  type:"object",
  properties:{
     name:{type:"string"},
     age:{type:"number"}
  }
};
instance = {
  name:"Kris",
  age:31
};
results = dojox.json.schema.validate(instance, schema);

This will validate the given instance against the schema. The validate function will return an object that indicates whether the instance is valid and provide the errors if it is not valid. In this case, results.valid will be true. If we were to validate an invalid instance:

instance = {
  name:"Kris",
  age:"pretty old"
};
results = dojox.json.schema.validate(instance, schema);

In this example, results.valid will be false, and the results.errors will be an array of the errors (in this case, the age property was a string instead of a number, as required).

JSON Schema can be used to describe the structure of virtually any set of data that can be represented in JSON. Much more sophisticated schemas can be defined. For example, to define an array of objects, we can create a schema:

schema = {
   items:{
     type:"object"
   }
};

Schemas can also be embedded in other schemas. To create an object with a property parts that expects an array of objects:

schema ={
   properties:{
     parts:{
        items:{
           type:"object"
        }
     },
     name:{
        type:"string"
     }
   }
};

A valid instance of this schema could be:

{
  name:"Camera",
  parts:[
    {partName:"Lens", partNum:3},
    {partName:"Battery", partNum:4}
  ]
}

You can create an enumeration of possible values for a property:

{
   properties: {
      gender:{
         type:"string",
         enum:["male","female"]
      }
   }
}

A valid instance could be:

{gender:"male"}

There are a number of constraints and information that can be associated with properties including regular expression pattern matching, length constraints, default values, and more. The JSON Schema specification includes more detailed information on definitions that can be created with JSON Schema.

JSON Schema + JsonRestStore

JSON Schema can also be used to maintain constraints on properties in items in the JsonRestStore. A schema can be provided to a JsonRestStore as a parameter on initialization:

// use the schema defined above
myStore = new dojox.data.JsonRestStore({target:"/target", schema: schema});

If a schema is provided to a JsonRestStore and dojox.json.schema is loaded (JsonRestStore doesn’t require it), all property changes will then be validated according to the schema. If the schema defines that the new value for a property is invalid according to the schema, the change will be rejected and an error will be thrown. For example:

var anItem = myStore.newItem();
// setting the name with a string value is allowed by the schema, this should work:
myStore.setValue(anItem, "name", "Kris");
// setting the age with a string value is not allowed by the schema, 
// this will throw an error:
myStore.setValue(anItem, "age", "kinda old");

Using a schema with JsonRestStore helps to ensure data integrity; invalid values can be detected early, rather than later when the data is sent to the server (although the server generally still needs to ensure data integrity as well). JSON Schema can be used for DRY data structure definitions.

JSON Schema is language agnostic and can be used to define data constraints on the server, thus providing a single schema that can be used on both the server and client side!

You can use a schema validated store to facilitate form validation. Values from a form can be set as properties on a target item, and the operation can be wrapped in a single try/catch to provide a single error handler for all the property sets.

Shared Schemas (JSON Referencing + JSON Schema)

JSON Schema is designed for the reuse of schemas. JSON Schema can utilize JSON Referencing to provide a mechanism for referencing schemas to reuse schema definitions and have a shared vocabulary of common JSON Schemas that can define interoperable data. One can utilize the JSON Referencing module in Dojo to resolve references prior to utilizing a schema. For example, if you had the following schema in a file:

{
  "id":"person",
  "properties":{
     "friends":{
        "item":{"$ref":"person"}
     }
  }
}

This defines a circular relationship, the schema for a person defines that the items in the friends array must also be valid instances of the person schema. We could load and resolve the references:

personSchema = dojox.json.ref.fromJson(personSchemaFile);
dojox.json.schema.validate(personInstance, personSchema);

One of the pitfalls of XML Schema has been the tendency to have widely varying incompatible definitions for essentially the same concept. JSON Schema is built to leverage referencing and provide the capability to extend existing schemas in order to have a shared set of reusable definitions. Schemas can reference other schemas from any location, but json-schema.org provides a set of reusable schemas based on currently available microformats. For example, one could define a schema for books and use the hcard microformat-style schema for defining the author:

{
  name:"Book",
  properties:{
    title:{type:"string"},
    author:{$ref:"http://json-schema.org/card"}
  }
}

This design makes referencing as simple as possible to encourage schema sharing, and with JSON Referencing’s basis on standard URI mechanisms, schema reuse can span a wide variety of uses.

Other Implementations of JSON Schema

A Python-based implementation of JSON Schema is available and from that same project you can download a standalone JavaScript library. Persevere implements JSON Schema, using schemas to define the structure of the objects in its data tables. Persevere then uses the schema to validate any new objects that are created or changes that are made to persistent objects (such as through the REST API), and reject changes that are not allowed by the schema. Therefore you can dynamically create ad-hoc type constraints on objects that are stored in Persevere.

The Service Mapping Description (SMD) uses JSON Schema to describe the acceptable values for all of the parameters and return values of the available web services.

Summary

JSON Schema provides a portable language-agnostic definition for describing object data structures. JSON Schema can be used for documenting, validating, and constraining data to facilitate interoperability and data integrity, and now Dojo provides a straightforward module for leveraging JSON Schema within the browser.