JSON Schema Validation
Introduction
RESTHeart supports MongoDB schema validation to enforce a format to documents: rules-based validation from MongoDB 3.2 and Json Schema validation from MongoDB 3.6, more in the MongoDB documentation.
On top of this, RESTHeart provides a more general approach for validation based on Checkers that can verify write requests based on any condition.
RESTHeart provides “out of the box” the jsonSchema Checker that validates the body of write requests against a JSON schema.
Compared to the internal MongoDB Json Schema validation, the jsonSchema Checker of RESTHeart provides additional advantages:
- schemas are stored in a special collection, the schema store
/_schemas
and are validated - schemas can and can be reused on multiple collections
- complex schemas can be defined using sub-schemas, i.e. using the $ref keyword
- documents can be validated using schemas that available online
- schemas are cached
JSON Schema
JSON Schema specifies a JSON-based format to define the structure of JSON data for validation, documentation, and interaction control. A JSON Schema provides a contract for the JSON data required by a given application, and how that data can be modified.
For more information about JSON Schema refer to json-schema.org; a very good resource is understanding json schema web site too.
The Schema Store and Schema resources
Schema Store resources allow store JSON schemas used for document validation; they are specialized collection resources whose documents must conform to the JSON schema format (specifically to the latest version draft-04)
Schema Store are first class citizens in RESTHeart and the format of
their URIs is /_schemas
Create the db schema store
PUT /_schemas HTTP/1.1
Schema resources are documents of the Schema Store. The following request creates a valid JSON Schema.
PUT /_schemas/address HTTP/1.1
{
"$schema": "https://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"address": { "type": "string" },
"city": { "type": "string" },
"postal-code": { "type": "string" },
"country": { "type": "string"}
},
"required": ["address", "city", "country"]
}
HTTP/1.1 201 Created
...
In JSON Schema, the id
property (not to be confused with the _id
key) has a special role. This property is auto-generated by RESTHeart as
can be noted in the response of the following GET request.
GET /_schemas/address HTTP/1.1
HTTP/1.1 200 OK
{
"$schema": "https://json-schema.org/draft-04/schema#",
"id": "https://schema-store/restheart/address#",
"_id": "address",
....
}
Document validation
To apply the jsonSchema checker simply define the collection
metadata property checkers
as follows:
{
"checkers": [{
"name": "jsonSchema",
"args": {
"schemaId": <schema_id> ,
"schemaStoreDb": <schema_store_db>
}
}]
}
Property
|
Description
|
Mandatory
|
---|---|---|
schemaId |
the _id of the JSON schema to enforce |
Yes |
schemaStoreDb |
the db | No, if omitted the current db is used. |
Example
Create a collection enforcing the address JSON Schema
PUT /addresses HTTP/1.1
{
"checkers": [{
"name": "jsonSchema",
"args": {
"schemaId": "address"
}
}]
}
Now let’s try to create an invalid document.
Try to create an invalid address
POST /addresses HTTP/1.1
{ "address": "Via D'Annunzio 28" }
HTTP/1.1 400 Bad Request
...
{
"_warnings": [
"#: 2 schema violations found",
"#: required key [city] not found",
"#: required key [country] not found"
],
"http status code": 400,
"http status description": "Bad Request",
"message": "request check failed"
}
Passing valid data results in the document creation:
Create a valid documents
POST /addresses HTTP/1.1
{
"address": "Via D'Annunzio, 28",
"city": "L'Aquila",
"country": "Italy"
}
HTTP/1.1 201 Created
Limitations
jsonChecker does not support the following requests:
- bulk PATCH
- bulk POST that use update operators
To handle this requests, set the checker property skipNotSupported to false
and add custom checkers to handle specific requests.
PATCH /addresses/*?filter={"country":"Italy"} HTTP/1.1
{ "updated": true }
HTTP 1.1 400 Bad Request
{
"_warnings": [
"the checker JsonSchemaChecker does not support this request and is configured to fail in this case. Note that the request is a bulk operation"
],
"http status code": 400,
"http status description": "Bad Request",
"message": "request check failed"
}
POST /addresses HTTP/1.1
[{
"address": "Via D'Annunzio, 28",
"city": "L'Aquila",
"country": "Italy"
"$currentDate": {
"timestamp": true
}
}]
HTTP 1.1 400 Bad Request
{
"_warnings": [
"the checker JsonSchemaChecker does not support this request and is configured to fail in this case. Note that the request uses update operators and it is a bulk operation"
],
"http status code": 400,
"http status description": "Bad Request",
"message": "request check failed"
}