Articles

JSONata Comes to ColdFusion: Query and Transform JSON Like a Pro

JSONata for CFML - JSON query and transformation language. Works on Adobe ColdFusion 206+ & Lucee 5-7 (No OS Extensions!)
April 1, 2026

If you've ever wrestled with deeply nested JSON structures in CFML - writing loop after loop, checking for key existence, and manually building transformed output - there's now a better way.

cfJSONata is a new open-source CFC that brings JSONata expression support to Adobe ColdFusion 2016+ and Lucee 5-7. Think of JSONata as XPath for JSON - a declarative query and transformation language that lets you extract, filter, aggregate, and reshape JSON data with compact expressions instead of procedural code.

What is JSONata?

JSONata is a lightweight query language designed specifically for JSON. It was created by Andrew Coleman at IBM and has been widely adopted in Node-RED, API gateways, and data integration tools. Instead of writing dozens of lines of code to navigate and transform JSON, you write a single expression.

For example, given an orders dataset, calculating the total of all line items is just:

$sum(orders.(quantity * price))

No loops. No temporary variables. One expression.

Why Does ColdFusion Need This?

Lucee recently released a platform-specific extension that adds a built-in JSONata() function - but only for Lucee 7.0.3+. Adobe ColdFusion users were left out, and even Lucee 5 and 6 users couldn't take advantage of it.

cfJSONata solves this by wrapping the jsonata-java library (the official Java port) in a CFML component that works across all modern CF engines. It's been tested and verified on:

  • Adobe ColdFusion 2016, 2021, 2023, 2025
  • Lucee 5, 6, 7

Quick Start

Download the jsonata-java JAR and the cfJSONata package from GitHub. Then:

// Load with explicit JAR paths
jsonata = new JSONata(jarPaths = [
    "/path/to/jsonata-0.9.9.jar",
    "/path/to/jsonata-cfml-bridge.jar"
]);

// Or use Application.cfc javaSettings to load JARs natively
jsonata = new JSONata();

// Query JSON data
data = { "name": "John", "age": 42 };
result = jsonata.evaluate("name", data);
// "John"

What Can It Do?

Extract deeply nested values

data = { "user": { "profile": { "city": "Atlanta" } } };
jsonata.evaluate("user.profile.city", data);
// "Atlanta"

Aggregate arrays

data = { "values": [1, 2, 3, 4, 5] };
jsonata.evaluate("$sum(values)", data);      // 15
jsonata.evaluate("$average(values)", data);  // 3
jsonata.evaluate("$count(values)", data);    // 5

Filter with predicates

data = {
    "products": [
        { "name": "apple", "price": 1.50 },
        { "name": "banana", "price": 0.75 },
        { "name": "cherry", "price": 3.00 }
    ]
};
jsonata.evaluate("products[price > 1].name", data);
// ["apple", "cherry"]

Transform and reshape data

data = { "firstName": "John", "lastName": "Smith" };
jsonata.evaluate('{ "fullName": firstName & " " & lastName }', data);
// { fullName: "John Smith" }

Pass variables into expressions

data = { "value": 10 };
jsonata.evaluate("value * $multiplier + $offset", data, { "multiplier": 5, "offset": 3 });
// 53

Register custom CFML functions

jsonata.evaluate(
    "$double(value)",
    { "value": 21 },
    {},
    {
        "functions": {
            "double": function(val) { return val * 2; }
        }
    }
);
// 42

Set timeout and recursion limits

jsonata.evaluate(expression, data, {}, { "timeout": 5000, "maxDepth": 50 });

Important: Quote Your Struct Keys

JSONata is case-sensitive, and CFML structs uppercase their keys by default. Always use quoted keys to preserve case:

// This won't work - "NAME" won't match the expression "name"
data = { name: "John" };

// This works - key stays lowercase
data = { "name": "John" };

How It Works Under the Hood

cfJSONata wraps the jsonata-java library (the official Java port of JSONata with zero external dependencies) and handles the CFML-to-Java bridge automatically:

  • Data conversion - CFML structs and arrays are converted to Java LinkedHashMap and ArrayList for compatibility with the Java library. JSON strings are parsed using the library's own parser.
  • Custom functions - A compiled Java bridge (jsonata-cfml-bridge.jar) handles the tricky part of calling CFML closures from Java code, supporting both Adobe CF's TemplateProxy and Lucee's CFC proxy patterns.
  • Error handling - Java exceptions are caught and re-thrown as typed CFML exceptions (JSONata.InvalidExpression, JSONata.Timeout, JSONata.RecursionLimit) for clean error handling in your application code.
  • Flexible JAR loading - Works with JARs on the classpath, via Application.cfc javaSettings, or loaded dynamically through JavaLoader.

Real-World Use Cases

  • API response processing - Extract and reshape data from external API responses without writing custom parsing code for every endpoint
  • Configuration-driven data mapping - Store JSONata expressions in a database or config file and apply them dynamically to transform data at runtime
  • Report generation - Aggregate, filter, and summarize data from complex JSON structures
  • Data validation - Use expressions to check data conditions and constraints
  • ETL pipelines - Transform JSON data between systems with minimal code

Get Started

The full source, documentation, and test suite are available on GitHub:

https://github.com/JamoCA/cfJSONata

The project is MIT licensed. The complete JSONata expression syntax is documented at docs.jsonata.org.