inndx
GitHub

Data schemas

The JSON Schema extensions data schemas support, beyond plain validation.

A data schema wraps a JSON Schema document as a named, storable resource used to validate extracted records (see Validating against a schema). The schema itself is plain JSON Schema (Draft 2020-12), but validation runs through an extended validator that adds a handful of x- keywords on top of standard validation: defaulting absent fields, computing fields from the rest of the document, pulling fields from external context, and transforming values before or after validation. This page documents that extended machinery.

$schema references are not supported; schemas are always validated against Draft 2020-12 directly.

How extended validation works

Each keyword below attaches to a single subschema (a property, array item schema, or the root) and is evaluated as part of a two-pass walk over the document:

  1. Before validation, for each node: if x-context is present, it supplies the value (overriding anything in the input). Otherwise the input value is used if present, falling back to x-default, falling back to a zero value for the schema's type ("", 0, false, [], {}, or null). Then x-before-transforms run on the result, in order.
  2. The document is validated against the plain JSON Schema, with x-* keywords ignored by the validator (they are not JSON Schema vocabulary).
  3. After validation, for each node: x-after-transforms run on the value, in order, then x-compute (if present) overwrites the value with a computed result that sees the whole validated document.

This means x-before-transforms and x-default/x-context can fix up data so it passes validation, while x-after-transforms and x-compute run on already-valid data and can themselves produce a value that no longer matches the schema. A failure at that point surfaces as json_schema_validation_failed, the same validation error used elsewhere, since the result is checked against the schema again.

x-default

Supplies a value for a field when it is missing from the input, before validation.

{
  "type": "string",
  "x-default": { "name": "literal", "params": { "value": "draft" } }
}
FieldTypeRequiredDescription
namestringyesThe registered default-value extension to use.
paramsobjectnoParameters passed to the extension.

literal

The only built-in default extension. Returns params.value verbatim, regardless of type.

x-compute

Overwrites a field with a computed value after the document has validated. The computation sees the entire validated document, so it can derive a field from sibling or unrelated fields.

{
  "type": "number",
  "x-compute": {
    "name": "expression",
    "params": { "expression": "root.price * root.quantity" }
  }
}
FieldTypeRequiredDescription
namestringyesThe registered computed-value extension to use.
paramsobjectnoParameters passed to the extension.

expression

The only built-in computed-value extension. Evaluates a CEL expression with the root document bound to the variable root, and returns the result as the field's value.

x-context

Sources a field's value from an external runtime context supplied by the caller, rather than from the input document. When present, it takes priority over the input value, x-default, and zero-value fallback.

{
  "type": "string",
  "x-context": { "expression": "context.tenant_id" }
}
FieldTypeRequiredDescription
expressionstringyesA CEL expression with the supplied context bound to the variable context.

There is no extension registry for x-context; it always evaluates as a CEL expression. The context value itself is supplied by the caller of validation, not by the document being validated; whether and what context is available depends on where validation is invoked. The available context when the schema is used within a parsing pipeline is:

FieldTypeDescription
urlstringThe URL of the document being parsed.
content_typestringThe content type of the document being parsed, if known.
assetsobjectThe assets extracted alongside the document.
run_idstringA unique identifier for this parsing run, if applicable.

The assets object has the asset types as keys and arrays of asset references as values. Each asset reference is an object with:

FieldTypeDescription
typestringThe asset type.
urlstringThe asset URL.
keystringThe blob storage key where this asset is stored.
metadataobjectThe asset reference metadata.

Where the metadata object contains:

FieldTypeDescription
content_typestringThe asset content type, if known.
content_lengthnumberThe asset content length in bytes, if known.
filenamestringThe asset filename, if known.
extensionstringThe asset file extension, if known.

x-before-transforms / x-after-transforms

Arrays of transforms applied to a field's value, in order. x-before-transforms run after the value is sourced (input, x-context, x-default, or zero value) but before validation; x-after-transforms run after validation, on the validated value.

{
  "type": "string",
  "x-before-transforms": [
    { "name": "coerce", "params": { "target": "string" } },
    { "name": "trim" }
  ]
}

Each entry is:

FieldTypeRequiredDescription
namestringyesThe registered transform to use.
paramsobjectnoParameters passed to the transform. Omit for transforms that take none.

coerce

Converts a string, number, or boolean value to another primitive type.

FieldTypeRequiredDescription
target"string", "number", "float", or "boolean"yesThe type to coerce the value to.

Coercion is between primitives only; arrays, objects, and null are not supported and fail the transform.

trim

Trims leading and trailing whitespace from a string value. Takes no parameters. Non-string values pass through unchanged.

Errors

Extended validation failures use the same error shapes as the rest of the API:

CodeWhen
invalid_json_schemaThe schema itself is not valid Draft 2020-12, or references $schema.
json_schema_validation_failedThe data does not match the schema, whether on the first pass or after x-after-transforms/x-compute run.
extension_errorA transform, default, or compute extension failed at runtime (for example, coerce on an unsupported value).
extension_compile_errorAn x-* keyword names an extension that is not registered, or a CEL expression fails to compile.

Search docs

Search the Self-host documentation