DevToys Web Pro iconDevToys Web ProBlogg
Betygsätt oss:
Prova webbläsartillägget:
← Back to Blog

JSONata Guide: Query and Transform JSON Like a Pro

10 min read

JSONata is an open-source query and transformation language for JSON data. Unlike JSONPath, which only selects values from existing structures, JSONata can compute new values, aggregate arrays, and build entirely new JSON shapes — all in a single expression. It powers the transformation layer in tools like IBM App Connect, Node-RED, and many low-code/iPaaS platforms.

Use the JSONata Tester to run every example in this guide interactively as you read.

JSONata vs JSONPath

The most important conceptual distinction: JSONPath is a selector — it navigates to existing nodes and returns them. JSONata is a transformation language — it evaluates expressions that can select, compute, reshape, and aggregate data simultaneously.

FeatureJSONPathJSONata
Select a fieldYes ($.user.name)Yes (user.name)
Filter array itemsYes ([?(@.price > 30)])Yes ([Price > 30])
Compute new valuesNoYes (Price * Qty)
Aggregate (sum, avg)NoYes ($sum(...))
Build new JSON shapesNoYes (object/array constructors)
String functionsLimited / impl-specificBuilt-in ($string, $uppercase, etc.)
Higher-order functionsNoYes ($map, $filter, $reduce)

If you only need to read a value out of a JSON document, both tools work. If you need to reshape, compute, or summarize, reach for JSONata. See also the JSONPath Cheatsheet for a deep-dive on the selector side.

Sample Data

All examples in this guide use the following invoice JSON:

{
  "Account": {
    "Name": "Firefly",
    "Order": [
      {
        "OrderID": "order001",
        "Product": [
          { "ProductName": "Bowler Hat", "ProductID": "prod1", "SKU": "0406654608", "Description": { "Colour": "Purple", "Width": 300, "Height": 200, "Depth": 210, "Weight": 0.75 }, "Price": 34.45, "Quantity": 2 },
          { "ProductName": "Cloak",      "ProductID": "prod2", "SKU": "040657863",  "Description": { "Colour": "Black",  "Width": 30,  "Height": 20,  "Depth": 210, "Weight": 2    }, "Price": 107.99, "Quantity": 1 }
        ]
      },
      {
        "OrderID": "order002",
        "Product": [
          { "ProductName": "Bowler Hat", "ProductID": "prod1", "SKU": "040657863",  "Description": { "Colour": "Purple", "Width": 300, "Height": 200, "Depth": 210, "Weight": 0.75 }, "Price": 34.45, "Quantity": 4 },
          { "ProductName": "Cloak",      "ProductID": "prod2", "SKU": "0406654603", "Description": { "Colour": "Black",  "Width": 30,  "Height": 20,  "Depth": 210, "Weight": 2    }, "Price": 107.99, "Quantity": 2 }
        ]
      }
    ]
  }
}

Path / Location Expressions

JSONata navigates JSON with dot-separated paths. No leading $. is required — paths are relative to the input by default. The expression Account.Name returns "Firefly". To reach deeply nested arrays, JSONata automatically flattens the intermediate arrays and returns a sequence:

Account.Order.Product.Price
// [34.45, 107.99, 34.45, 107.99]

Account.Order.Product.ProductName
// ["Bowler Hat", "Cloak", "Bowler Hat", "Cloak"]

Account.Order[0].OrderID
// "order001"  (zero-based index)

This automatic sequence flattening is one of the key ways JSONata differs from JSONPath: you navigate paths naturally without manually specifying wildcards.

Predicates (Filters)

Predicates narrow a sequence using [condition] syntax. The condition is evaluated against each item; only items where the condition is truthy survive. Use $ inside a predicate to reference the current item:

Account.Order.Product[Price > 30]
// both Bowler Hats and both Cloaks (all prices > 30)

Account.Order.Product[Price > 100]
// [{"ProductName": "Cloak", ...}, {"ProductName": "Cloak", ...}]

Account.Order.Product[Quantity > 1].ProductName
// ["Bowler Hat", "Bowler Hat", "Cloak"]

Account.Order[OrderID = "order002"].Product.ProductName
// ["Bowler Hat", "Cloak"]

Aggregation and Higher-Order Functions

JSONata ships with a rich standard library. The aggregation functions — $sum, $average, $min, $max, $count — all accept a sequence and return a scalar. Higher-order functions like $map, $filter, and $reduce accept a sequence and a lambda expression written as function($v, $i, $a){...}.

$sum(Account.Order.Product.Price)
// 285.88  (sum of all four prices)

$average(Account.Order.Product.Price)
// 71.47

$count(Account.Order.Product)
// 4

$sum(Account.Order.Product.(Price * Quantity))
// 460.77  (line totals: 34.45*2 + 107.99*1 + 34.45*4 + 107.99*2)

$map(Account.Order.Product.Price, function($v) { $round($v, 0) })
// [34, 108, 34, 108]

$filter(Account.Order.Product, function($p) { $p.Price < 50 }).ProductName
// ["Bowler Hat", "Bowler Hat"]

$reduce(Account.Order.Product.Quantity, function($a, $b) { $a + $b })
// 9  (total units across all line items)

Object and Array Constructors

The most powerful JSONata feature is building new JSON structures. Object constructors use {key: expression} syntax; wrapping an expression in [] forces an array. This makes JSONata ideal for reshaping API responses before passing them downstream.

/* Reshape: produce a summary object */
{
  "customer": Account.Name,
  "orderCount": $count(Account.Order),
  "productCount": $count(Account.Order.Product),
  "grandTotal": $sum(Account.Order.Product.(Price * Quantity)),
  "cheapestItem": $min(Account.Order.Product.Price)
}

/* Output */
{
  "customer": "Firefly",
  "orderCount": 2,
  "productCount": 4,
  "grandTotal": 460.77,
  "cheapestItem": 34.45
}

You can also produce an array of reshaped objects by mapping over a sequence inside []:

Account.Order.Product.{
  "name": ProductName,
  "lineTotal": Price * Quantity,
  "heavy": Description.Weight > 1
}

/* Output one object per product line */
[
  { "name": "Bowler Hat", "lineTotal": 68.90,  "heavy": false },
  { "name": "Cloak",      "lineTotal": 107.99, "heavy": true  },
  { "name": "Bowler Hat", "lineTotal": 137.80, "heavy": false },
  { "name": "Cloak",      "lineTotal": 215.98, "heavy": true  }
]

String and Number Functions

JSONata includes string manipulation and numeric utilities you would normally handle in application code:

FunctionExampleResult
$string(val)$string(34.45)"34.45"
$number(val)$number("107")107
$uppercase(str)$uppercase("cloak")"CLOAK"
$lowercase(str)$lowercase("Firefly")"firefly"
$trim(str)$trim(" hello ")"hello"
$substring(str, start, len)$substring("Bowler Hat", 0, 6)"Bowler"
$split(str, sep)$split("a,b,c", ",")["a","b","c"]
$join(arr, sep)$join(["a","b"], "-")"a-b"
$round(num, dp)$round(107.999, 2)108
$abs(num)$abs(-5)5

Real-World Use Cases

Reshaping an API Response

iPaaS platforms and low-code tools often need to map a vendor API shape to an internal schema. JSONata lets you declare the mapping as a pure expression with no procedural code:

/* Map vendor invoice internal order format */
{
  "id": Account.Order[0].OrderID,
  "vendor": Account.Name,
  "items": Account.Order[0].Product.{
    "sku": SKU,
    "qty": Quantity,
    "unitPrice": Price,
    "total": $string($round(Price * Quantity, 2))
  },
  "orderTotal": $sum(Account.Order[0].Product.(Price * Quantity))
}

Config Mapping and Feature Flags

When merging configuration objects from multiple sources, JSONata predicates and $merge let you compose the final config declaratively. Because expressions have no side effects, they are safe to evaluate in serverless or edge environments.

Try It in the JSONata Tester

Copy any expression from this guide and paste it into the JSONata Tester. The tester evaluates expressions in the browser using the official jsonata library, so results are always accurate. You can also import your own JSON payloads to test transformations against real data before deploying them to production pipelines.

  • Paste your API response as the JSON input
  • Write a JSONata expression to reshape or aggregate the data
  • Inspect the output and iterate immediately — no server round-trips
  • Compare JSONata path expressions with JSONPath selectors side by side to choose the right tool for your use case

JSONata is a surprisingly complete language for data transformation work that would otherwise require custom code. Its path expressions, predicates, aggregation functions, and object constructors cover the vast majority of JSON reshaping tasks in API integrations and low-code workflows. Start experimenting with the JSONata Tester to see how much transformation logic you can move out of your application layer and into a declarative expression.