> IronFlow documentation for v1.20.0. [HTML version](https://ironflow.work/docs/nodes/json_validate) · [Release source](https://github.com/skitsanos/ironflow/blob/v1.20.0/docs/nodes/json_validate.md)

# `json_validate`

Validate JSON from context against a JSON Schema.

## Parameters

| Parameter    | Type   | Required | Default | Description                                                                    |
|--------------|--------|----------|---------|--------------------------------------------------------------------------------|
| `source_key` | string | Yes      | --      | Context key containing either a JSON string, or a value already decoded as JSON |
| `schema`     | object/boolean | No* | -- | A JSON Schema to validate the data against |
| `schema_key` | string | No* | -- | Context key containing a decoded JSON Schema or JSON Schema string |

*Provide exactly one of `schema` or `schema_key`.

If the value is a string, `json_validate` first parses it as JSON, then validates the result.  
If the value is already a JSON object/array/etc., it is validated directly.

## Schema References

Validation is offline-only. References bundled in the supplied schema work;
references requiring network or file retrieval fail normally without fetching.
See [JSON Schema validation](https://github.com/skitsanos/ironflow/blob/v1.20.0/docs/JSON_SCHEMA_VALIDATION.md) for bundled-reference
examples, error behavior, and cancellation boundaries.

## Context Output

- `validation_success` — boolean indicating whether validation passed
- `validation_errors` — array of validation error strings (empty on success)

The node returns a structured error when validation fails. Downstream steps are
skipped unless a dedicated `on_error` handler runs successfully and resolves
the failure. After retries are exhausted, the final validation result is
buffered for the source phase barrier and the handler receives its source-exact
copy in `_error_output`. Normal shared keys still follow declaration-order
collision precedence if a parallel step publishes the same names.

## Example

```lua
local flow = Flow.new("json_validate_example")

flow:step("validate", nodes.json_validate({
    source_key = "payload_json",
    schema = {
        type = "object",
        required = { "id", "name" },
        properties = {
            id = { type = "string" },
            name = { type = "string" },
            age = { type = "integer", minimum = 0 }
        }
    }
}))

flow:step("ok", nodes.log({
    message = "Payload JSON passed validation."
})):depends_on("validate")

return flow
```

### Validate with a schema loaded from a file

```lua
local flow = Flow.new("json_validate_from_file")

flow:step("read_schema", nodes.read_file({
    path = "schemas/payload.schema.json",
    output_key = "schema"
}))

flow:step("validate", nodes.json_validate({
    source_key = "payload_json",
    schema_key = "schema_content"
})):depends_on("read_schema")

return flow
```
