Structured data · Core reference
JSON data.
@json(path, name) loads a JSON document into the current page render. Access values through the same $[...] syntax used for metadata, with object and array access chained as deeply as the data requires. An optional third parameter can validate that data against a standard JSON Schema before rendering.
Nift can load and select JSON values without turning the template language into a general-purpose programming language. Use ordinary external tools when you need substantial data transformation.
Load a document
@json('data/site.json', site) The first parameter is a project-relative JSON path. The second is the binding name used for the rest of that page render, including nested @input files.
Source and optional schema paths are textual parameters, so an earlier binding can select them with $[...]. Binding names remain static identifiers:
@json('data/selector.json', selector)
@json("data/$[selector.dataset].json", selected,
"schemas/$[selector.schema].json") {
"name": "Nift",
"navigation": [
{"title": "Home", "url": "/"},
{"title": "Docs", "url": "/docs/"}
],
"features": {
"search": true
}
} @json('data/site.json', site)
<h1>$[site.name]</h1>
<a href="$[site.navigation[1].url]">
$[site.navigation[1].title]
</a> Optionally validate the data's shape
@json('data/products.json', products, 'schemas/products.schema.json') The optional third parameter is a JSON Schema. Nift validates the document before binding it and records both the data file and schema as dependencies. This catches problems such as missing required fields, wrong types, invalid enum values, unexpected properties and values outside declared bounds at build time.
If JSON Schema is new to you, the dedicated guide starts from first principles and includes complete examples.
JSON Schema validation explains the standard, Nift's supported subset, reusable $defs/$ref, validation errors and incremental dependency behaviour.
Access can chain arbitrarily
$[data.sections[3].groups[0].items[12].author.name]
$[data.matrix[2][4]]
$[data.settings.navigation.mobile.enabled] Objects use .member; arrays use zero-based [index]. You can alternate them as often as the document shape requires.
Scalar output
| JSON value | Template output |
|---|---|
| string | The string contents |
| number | The JSON number |
| boolean | true or false |
null | null |
| array/object | Build error: select an element/member rather than implicitly serialising the whole structure. |
The JSON file is automatically a dependency
Loading:
@json('data/navigation.json', nav) also tells Nift that the current page depends on data/navigation.json. A change to that data can therefore trigger build-updated in modified, hash or hybrid mode just like a template/input dependency.
Parsed documents are shared per build
If thousands of pages load the same JSON file, Nift does not need to parse the document thousands of times. Parsed documents are cached as immutable build-wide data, while the binding name remains local to each page parser.
data/site.json
│
└── parsed once for this build
│
├── page A: binding "site"
├── page B: binding "site"
└── page C: binding "settings" That is safe to share because the JSON document itself is immutable. Page-specific rendered partials are not cached in the same way.
Binding names
Names use identifier-style letters/digits/underscores and cannot conflict with built-in metadata names. Rebinding the same name is an error rather than silently replacing earlier data.
Use it with control flow when the data actually needs it
@json('data/articles.json', data)
@for(article : data.articles){
@if(article.published){
<article>
<h2>$[article.title]</h2>
</article>
}
} If your JSON only contains a few scalar settings, you may never need a loop or condition. Load exactly what the page needs.
Failures are explicit
Nift reports malformed JSON, missing files, invalid binding names, traversal attempts, missing members, bad array indices, wrong value types and attempts to render whole objects/arrays as build errors with source context.