Skip to content

JSON Schema Validation

Yauheni Zablotski edited this page Jul 4, 2016 · 6 revisions

JSON Schema Validation

If you use Jsonix Schema Compiler to compile your schemas, you may also generate an accompanying JSON Schema. See JSON Schema Generation for more information on this feature.

What you basically need to do is just add the -generateJsonSchema command-line option when calling Jsonix Schema Compiler.

As the result, Jsonix Schema Compiler will produce MySchema.jsonschema files which are JSON Schemas matching your MySchema.js Jsonix mappings. See Understanding the Generated JSON Schema for an explanation of the generated JSON Schema.

You can use the generated JSON Schema to validate your JSON - before marshalling or after unmarshalling. For this, you'll need to use a JSON Schema validator for this.

Choosing the JSON Schema Validator

Jsonix Schema Compiler produces standards-conforming JSON Schema, so theoretically any conforming JSON Schema validator should work. However, in practice schema validators differ pretty much in how far they comply to the standards. Check the following benchmark which also tests standard conformance.

JSON Schemas generated by the Jsonix Schema Compiler reference external schemas, i.e.:

This means that you'll need a validator which has good support for external schemas.

After some testing, I highly recommend AJV which is highly complying JSON Schema validator which also provides very good support for external schemas.

Validating JSON using AJV and the generated JSON Schemas

Assume we compile the Purchase Order schema and turn on JSON Schema generation using the -generateJsonSchema command-line option:

java -jar jsonix-schema-compiler-full.jar -generateJsonSchema -d mappings purchaseorder.xsd -b bindings.xjb

As a result we'll get a PO.jsonschema file in the mappings directory, just next to the PO.js (generated Jsonix mappings).

To validate with AJV, we'll first need to create the validate function by loading and compiling relevant schemas:

var fs = require('fs');
var Ajv = require('ajv');

var XMLSchemaJsonSchema = JSON.parse(fs.readFileSync('./node_modules/jsonix/jsonschemas/w3c/2001/XMLSchema.jsonschema').toString());
var JsonixJsonSchema = JSON.parse(fs.readFileSync('./node_modules/jsonix/jsonschemas/jsonix/Jsonix.jsonschema').toString());
var POJsonSchema = JSON.parse(fs.readFileSync('./mappings/PO.jsonschema').toString());

var ajv = new Ajv();
ajv.addSchema(XMLSchemaJsonSchema, 'http://www.jsonix.org/jsonschemas/w3c/2001/XMLSchema.jsonschema');
ajv.addSchema(JsonixJsonSchema, 'http://www.jsonix.org/jsonschemas/jsonix/Jsonix.jsonschema');
var validate = ajv.compile(POJsonSchema);

A short explanation for the code above.

As mentioned above, PO.jsonschema uses JSON Schemas http://www.jsonix.org/jsonschemas/w3c/2001/XMLSchema.jsonschema and http://www.jsonix.org/jsonschemas/jsonix/Jsonix.jsonschema. These JSON Schemas are available online but also shipped with the Jsonix NPM module. You can access this files from node_modules/jsonix/jsonschemas:

var XMLSchemaJsonSchema = JSON.parse(fs.readFileSync('./node_modules/jsonix/jsonschemas/w3c/2001/XMLSchema.jsonschema').toString());
var JsonixJsonSchema = JSON.parse(fs.readFileSync('./node_modules/jsonix/jsonschemas/Jsonix/Jsonix.jsonschema').toString());

Next, you'll need to make these schemas available to AJV using the addSchema(...) function:

ajv.addSchema(XMLSchemaJsonSchema, 'http://www.jsonix.org/jsonschemas/w3c/2001/XMLSchema.jsonschema');
ajv.addSchema(JsonixJsonSchema, 'http://www.jsonix.org/jsonschemas/jsonix/Jsonix.jsonschema');

Finally, we'll need to load and compile our primary JSON Schema, PO.jsonschema, getting the validation function as a result:

var POJsonSchema = JSON.parse(fs.readFileSync('./mappings/PO.jsonschema').toString());
...
var validate = ajv.compile(POJsonSchema);

Now we're ready to validate JSON. Assume we're loaded our data in the po variable:

var po = JSON.parse(fs.readFileSync("tests/po.json").toString());

Validation with AJV is as simple as:

var valid = validate(po);
if (!valid) {
	console.log('Validation failed.');
	console.log('Validation errors:');
	console.log(validate.errors);
}

For example, imagine we've mistaken in the orderDate field, confusing month and date:

        "orderDate": {
            "year": 1999,
            "month": 20,
            "day": 10
        }

Tha validation will fail, producing the following report:

Validation failed.
Validation errors:
[ { keyword: 'maximum',
    dataPath: '.value.orderDate.month',
    message: 'should be <= 12' },
  { keyword: 'type',
    dataPath: '.value.orderDate',
    message: 'should be null' },
  { keyword: 'anyOf',
    dataPath: '.value.orderDate',
    message: 'should match some schema in anyOf' },
  { keyword: 'type',
    dataPath: '.value',
    message: 'should be string,null' },
  { keyword: 'anyOf',
    dataPath: '',
    message: 'should match some schema in anyOf' } ]

Example

Please see the following project for example: