Hookway

Validate JSON

json_validate checks an event body against a JSON Schema before the flow delivers it. It verifies shape and values; it does not serialize a Go object or generate application types. Place it after a JSON envelope and before the nodes that depend on the checked fields.

The builder calls the same Go validator through WASM when you test a sample. The editor API exposes the same operation for connected clients. Validation does not fetch schemas or initialize databases, brokers, or credentials.

Configuration

- id: check
  type: json_validate
  schema:
    type: object
    required: [order_id, customer]
    additionalProperties: false
    properties:
      order_id: {type: integer, minimum: 1}
      customer:
        type: object
        required: [email]
        properties:
          email: {type: string, format: email}
        additionalProperties: false

The top-level schema must be a nonempty object. Nested boolean schemas, objects, arrays, nullable unions, required properties, numeric constraints, and format constraints follow the selected JSON Schema draft. Draft 7 is the default. An explicit $schema may select Draft 4, 6, 7, 2019-09, or 2020-12. Local $ref references work, including definitions in the same schema; references requiring another resource are rejected at configuration validation. Known formats are checked even in drafts where they are normally annotations.

Required fields must be listed in required. Writing a field under properties alone does not make it required. Additional fields are allowed unless the schema constrains them, for example with additionalProperties: false. A default annotation does not insert missing values. Validation does not strip extra fields or turn strings into numbers automatically.

See the complete runnable example for local references and an HTTP response. Its no_auth node is for demonstration; use an appropriate authentication node on a production endpoint.

Explicit conversions

  coercions:
    - {path: order_id, type: integer}

A conversion applies before validation, only at the listed dotted property path. Each path must resolve through literal properties entries, and the property must declare exactly one type matching the conversion. Paths through $ref, arrays, union types, or anyOf do not authorize conversion. Conversion paths are limited to 256 characters and 64 entries.

The existing scalar conversion rules are retained:

TargetAccepted conversions
stringStrings stay strings; numbers become exact decimal text; booleans become "true" or "false"; null becomes an empty string.
number / integerBounded numeric strings, including supported hexadecimal float syntax, become exact numbers. Null becomes zero and booleans become zero or one. Integers require an exact integral value.
booleanBooleans stay booleans; strings "true" and "false", JSON number literals 1 and 0, and null convert. Null becomes false.
nullNull, an empty string, false, and an exact numeric zero become null.

Missing fields are not created. If a value cannot be converted, it retains its original value and the schema decides whether it is valid. Objects and arrays are not scalar conversions. For example, "42" can become an integer; "4.2" cannot become an integer. No precision is lost when converting "9007199254740993" to an integer.

Failures and precision

Invalid JSON, a non-JSON envelope, schema mismatch, or a body limit violation returns HTTP 400 by default. A normal success edge carries the validated envelope. Wire check:on_error>rejected to use the existing error recovery path, for example an explicit 422 response. The failure path retains the original input. Neither validation nor conversion mutates another branch's input or the raw request bytes.

JSON envelope decoding, graph cloning, validation, and explicit numeric conversions preserve exact numeric values. Validation without conversions also preserves the parsed values and number representations. Upstream JavaScript or other transformations can change numeric values independently; place validation before those steps when the original numeric value matters.

The builder stores schemas as JavaScript objects. It rejects schema numeric literals that would change when parsed and exported, including unsafe large integers and high-precision decimals. It also rejects ambiguous leading-zero YAML numbers and numeric YAML syntax its parser would interpret as a string. Use ordinary decimal notation for builder-authored schemas. For constraints that JavaScript cannot retain exactly, author and validate runtime YAML directly. Rejected imports leave the current graph unchanged. Invalid schema drafts remain editable and block export until corrected or reverted.

Samples and validated output travel as JSON text, so their large integers and decimals remain exact in the builder. The sample is retained in local editor drafts and is excluded from exported configuration. Editing the schema, sample, or conversions clears the previous result; late responses cannot overwrite a newer edit.

Limits and API contract

Input or outputLimit
Encoded schema256 KiB, depth 64, 10,000 nodes
Runtime body presented to validation20 MiB, depth 128, 1,000,000 nodes; ingress may impose a lower body limit
Numeric work4,096 characters of numeric input and exponent magnitude at most 4,096
Validation workExpanded schema cost at most 10,000; estimated node work at most 1,000,000 and text/digit work at most 32 MiB, including conservative uniqueness comparisons
Sample text1 MiB
Sample request envelope8 MiB, allowing JSON escaping
Sample output2 MiB
Reported sample issuesAt most 64

POST /json-sample-validation takes schema, optional coercions, and a sample string. A schema/sample validation result is HTTP 200 with valid, an issues array, and an output JSON string on success. Malformed request envelopes return 400; an oversized request returns 413. The route uses the editor's existing authentication and CORS rules. The generated editor API specification defines these DTOs.

WASM capability json_sample_validate invokes hookwayJSONSampleValidate with the same input and result. The public static builder uses WASM. The Go-hosted editor can fall back to its editor API. An unavailable validator is shown explicitly; it does not count as a successful sample check. Issue paths are JSON pointers and messages identify constraints without echoing submitted values. Property names may appear in paths.

The work estimate counts every possible schema branch, regular-expression length, body strings/property names/numeric digits, and recursive references through the supported body depth. It is deliberately conservative: large schema/body combinations may be rejected even when they fit the byte and structure limits. Repeated references cannot bypass it to generate an exponentially large validation/error tree.

Existing configurations

Existing transform nodes with kind: json_schema, json_schema, and coercions use the same engine and builder controls. No migration is required. Runtime construction propagates schema compilation errors.

Try valid and invalid samples in the builder, then export the resulting YAML. Validate the runnable example with go run ./cmd/hookway validate --config examples/json-validation.yaml.