Articles
JSONata Comes to ColdFusion: Query and Transform JSON Like a Pro
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
LinkedHashMapandArrayListfor 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'sTemplateProxyand 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.cfcjavaSettings, 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.