JSON validation
By default, Modélico does not validate JSON in any special way. Moreover, the JSON is coerced when the metadata defined doesn't match the actual value, eg. if a field has string() as its metadata, but there is a number in the incoming JSON, it will be coerced with String(5).
To validate the JSON strictly, you have the following options:
use
M.ajvMetadatafor Ajv's implementation of JSON schema;manually create validation functions that work as revivers;
a bit of both;
alternatively, you can also override the reviver with your own.
M.ajvMetadata and JSON schema
M.ajvMetadata and JSON schemaThis variation of M.metadata() takes an optional Ajv instance parameter and returns metadata functions that take an additional parameter in the form of JSON schema for the current field. When no instance of Ajv is passed in, it returns metadata functions with the same API but no validation is performed. This can be leveraged to only enable validation during development in favour of faster parsing in production:
import Ajv from 'ajv'
const ajvOptions = {}
const ajvIfProd = (ENV === 'development') ? Ajv(ajvOptions) : undefined
const {string, list, number} = M.ajvMetadata(ajvIfProd)
class Animal extends M.Base {
static innerTypes() {
return Object.freeze({
name: string({minLength: 1, maxLength: 25}),
dimensions: list(
number({exclusiveMinimum: 0}),
{minItems: 3, maxItems: 3}
)
})
}
}Note: if you are using Modélico in the browser, you need to load Ajv as it is not bundled with Modélico. See instructions here.
Custom validation metadata
If you only need to validate certain fields or you have custom rules that are not covered by what JSON schema can validate, you may write your own metadata. M.withValidation facilitates this use case.
Why not both?
In the example above, we could have based lowerCaseString on the ajvMetadata-string instead of the normal string to combine custom and JSON schema rules.
M.withValidation works with any metadata, including the Ajv variant and can be composed, since it returns a function that takes metadata and returns metadata.
The error message function gets the path where the metadata is used to help debugging complex deep objects.
Now we can define fields with something like stringWithoutNumbersAndLowerCase({minLength: 5}).
Please note that although it might be tempting to compose the validation functions and use M.withValidation only once with the result, by using M.withValidation for each individual function you can attach specific error messages to simplify debugging.
Overriding the reviver
If you need to validate the JSON in a way not covered by the examples above, you may override the reviver with your own. This might be needed if the validity of some fields depends on other fields. In the following example, we make sure that min <= max in a Range class:
In the class above, the validation could happen in the constructor. Although that would ensure direct use of the class or creation of new instances via set are also valid, it is sometimes preferable to consider internal use of the class as trusted and only validate external JSON.
One-off validations can be performed with M.validate, which takes a Modélico instance, optional inner metadata for generic types, and returns an array with 2 items: the result of the validation (boolean), and an Error if the validation was not successful.
Using the class:
Last updated