-
Notifications
You must be signed in to change notification settings - Fork 78
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.
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.:
-
http://www.jsonix.org/jsonschemas/w3c/2001/XMLSchema.jsonschema
- JSON Schema for XML Schema types. -
http://www.jsonix.org/jsonschemas/jsonix/Jsonix.jsonschema
- JSON Schema for Jsonix types.
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' } ]
Please see the following project for example: