Skip to content

JSONata

Evaluate JSONata expressions against JSON values from inside DuckDB SQL.

38,785
extension loads · last 90 days
On this page

Technical Overview

When to Reach for JSONata over json_extract

JSONata vs. chains of json_extract

  • Array predicate filters: Phone[type="mobile"].number selects matching elements and projects in one step. The native equivalent extracts the array, unnests it, filters with a WHERE, and projects in a correlated subquery.
  • Object reshaping: An object-construction literal builds a fresh JSON object — pulling, renaming, and computing fields together. Natively that's one json_extract_string per output field, which gets unwieldy past two or three fields.
  • Embedded aggregation and higher-order ops: $sum, $count, $max and $map, $filter, $reduce operate on arrays inside the document, keeping per-row roll-ups inline instead of leaving the JSON value to unnest and re-aggregate.
  • The break-even: Roughly: any array predicate, any reshape, or more than two output fields tilts toward JSONata. A single field at a fixed path stays simpler in native DuckDB JSON — don't add an extension for it.

How it works

  • Constant expressions are parsed once: When the expression argument is a SQL constant — by far the common case — the parser runs a single time and the compiled program is reused for every row. Per-row cost is then just the JSON walk plus operator application, not a parse-and-compile on each row, so a static expression over a million rows still parses exactly once.
  • JSON in, JSON out: Both the input value and the return type are JSON. Cast or unnest downstream depending on what the expression yields — result::VARCHAR, result->>'$', or unnest(result::JSON[]) for arrays — exactly like any other DuckDB JSON expression.
  • Two arities, parse cache intact: The 3-arg form takes a bindings JSON object whose keys become $variable names inside the expression. This is how you pass per-query values — thresholds, ids, dates — into an otherwise static expression without breaking the parse-once optimization, since the expression text stays constant.

Scope and caveats

  • Single scalar function surface: Everything is reached through one function — there are no helper UDFs for individual JSONata operators. The expression string carries the whole computation. (It is not a JSON loader either; use DuckDB's read_json for that.)
  • Expressions are SQL strings: JSONata expressions live inside a SQL VARCHAR literal, so embedded double quotes need SQL escaping. For long or fiddly expressions, store them in a CTE or a SQL variable and reference by name — and iterate in the official JSONata exerciser, whose evaluator matches what the extension runs.
  • No DuckDB-UDF callbacks: JSONata's JavaScript-binding feature isn't wired up — you can't register a DuckDB function as a callable inside the expression. Stick to JSONata's built-in function library.
  • Per-row cost scales with document and expression size: Deeply-nested documents and complex expressions both cost, and they scale linearly with the data they touch. For very wide rows, materialize the JSONata projection once into a column instead of re-evaluating it in every downstream query.

Deep Dive

Technical Details

Install

INSTALL jsonata FROM community;
LOAD jsonata;

Quick Start

Extract a nested field

SELECT jsonata('Account.Name',
               '{"Account":{"Name":"Firefly"}}');

Filter an array with a predicate, then project

SELECT jsonata('Phone[type="mobile"].number', payload)
FROM contacts;

Reshape JSON in one expression

SELECT jsonata('{
  "name":   FirstName & " " & Surname,
  "mobile": Phone[type="mobile"].number
}', payload) AS reshaped
FROM contacts;

Reference

Extension Contents

Quick reference to all available functions and settings organized by category.

Name Description
Functions
jsonata() Evaluates a JSONata expression against a JSON document and returns the result as JSON.

API Reference

Function Documentation

Practical Examples

Cookbook

Real-world recipes and patterns for common use cases.

Platform Support

Compatibility

Extension availability may vary by platform and DuckDB version. Check below to ensure this extension supports your environment before installation.

Quick Facts

Release status Stable
Software License MIT
Pricing Free
Written In C++
Source Available Yes
View on GitHub
Usage
38,785
loads · last 90 days

Platforms

  • Linux x86_64 aarch64
  • Linux (musl) Not available
  • macOS Intel Apple Silicon
  • Windows x86_64
  • WASM eh mvp threads
Compiled binary sizes
Platform Architecture Size
Linux x86_64 3.77 MB
Linux aarch64 3.36 MB
macOS Intel 1.90 MB
macOS Apple Silicon 1.74 MB
Windows x86_64 7.74 MB
WASM eh 336.3 KB
WASM mvp 393.2 KB
WASM threads 336.1 KB

Compressed download size from the Haybarn extension repository.

DuckDB & Haybarn

Release calendar