JSON-Schema Validation
crate.validation.jsonSchema validates a vibe Json value against a JSON-Schema document. It covers the subset Crate’s own generated schemas use, has no dependencies beyond vibe.data.json, and is a pure function — no I/O, no allocation of a validator object.
import crate.validation.jsonSchema;
auto errors = validate(schema, data);
if (errors.length > 0) { foreach (error; errors) { logError("%s: %s", error.path, error.message); }}An empty result means the value is valid.
SchemaError
Section titled “SchemaError”struct SchemaError { string path; string message;}path is a dot-separated JSON path to the offending value, built as the validator descends: address.city, tags.0.name. It is empty for an error on the root value. Array indices appear as plain numeric segments.
Supported Keywords
Section titled “Supported Keywords”| Keyword | Applies to | Behavior |
|---|---|---|
type | any | string, number, integer, boolean, object, array, null. An unrecognized type name always passes |
properties | objects | Validates each named property that is present; absence is required’s business |
required | objects | Reports one error per missing property, with the property name as the path |
items | arrays | Applies one schema to every element |
enum | any | The value must equal one of the listed values |
oneOf | any | The value must match exactly one branch — zero matches and two matches are both errors |
$ref | any | Resolves #/$defs/<name> against the root schema’s own $defs |
number accepts both integers and floats; integer accepts only integers.
Limits
Section titled “Limits”This is deliberately a subset, and unknown keywords are ignored rather than rejected. Not implemented: allOf, anyOf, not, patternProperties, additionalProperties, minimum/maximum, minLength/maxLength, pattern, format, uniqueItems, minItems/maxItems, and $ref to anything outside the schema’s own $defs. A schema using them validates as if those keywords were absent — it will not report an error for them, and it will not fail loudly either.
Two resolution rules fail open rather than erroring:
- A
$refthat does not start with#/$defs/, or names a definition that is not in$defs, is skipped. - An unrecognized
typename matches anything.
Null Means Unset
Section titled “Null Means Unset”A null value satisfies any schema. Legacy data uses an explicit null to mean “this optional field has no value”, and rejecting it would fail records that are intentionally empty. The key is still present, so required is satisfied — required asks whether the property exists, not whether it holds a value.
If you need “present and not null”, check for it separately after validation.