Back to all posts
Tutorial
8 min read

What Is JSONata? Learn How to Query JSON Like a Pro

DevToolLab Team

DevToolLab Team

April 25, 2025 (Updated: May 30, 2025)

What Is JSONata? Learn How to Query JSON Like a Pro

What Is JSONata? Learn How to Query JSON Like a Pro

JSON (JavaScript Object Notation) has become the standard format for data exchange in modern web applications. As applications grow in complexity, the need for effective ways to query and transform JSON data becomes increasingly important. This is where JSONata comes into play a lightweight, powerful query and transformation language specifically designed for JSON.

What is JSONata?

JSONata is an open-source query and transformation language for JSON data. Created by Andrew Coleman at IBM, it provides a concise and elegant way to extract, transform, and combine data from JSON documents. Think of it as "XPath for JSON" - a purpose-built language that makes complex JSON operations simple.

Key Features of JSONata

1. Path Navigation

The most basic feature of JSONata is the ability to navigate through JSON structures using path expressions:

JSON
// Sample JSON data
{
  "customer": {
    "name": "John Smith",
    "address": {
      "city": "New York",
      "zipCode": "10001"
    },
    "orders": [
      { "id": "1001", "product": "Laptop", "price": 1200 },
      { "id": "1002", "product": "Smartphone", "price": 800 }
    ]
  }
}

To access the customer's city:

customer.address.city

Result: "New York"

Path Navigation in JSONata

Path Navigation in JSONata

2. Array Processing

JSONata makes working with arrays intuitive:

customer.orders.product

Result: [ "Laptop", "Smartphone" ]

Array Processing in JSONata

Array Processing in JSONata

3. Filtering and Conditions

You can use conditions to filter data:

customer.orders[price > 1000].product

Result: "Laptop"

Filtering and Conditions in JSONata

Filtering and Conditions in JSONata

4. Functions and Transformations

JSONata includes built-in functions and allows custom functions for data transformation:

$sum(customer.orders.price)

Result: 2000

Functions and Transformations in JSONata

Functions and Transformations in JSONata

5. Data Restructuring

Easily reshape your data:

{
  "customerName": customer.name,
  "totalSpent": $sum(customer.orders.price),
  "orderCount": $count(customer.orders)
}

Result:

JSON
{
  "customerName": "John Smith",
  "totalSpent": 2000,
  "orderCount": 2
}

Data Restructuring in JSONata

Data Restructuring in JSONata

When to Use JSONata

JSONata is particularly useful in scenarios where you need to:

  • Extract specific data from complex JSON documents
  • Transform JSON data from one structure to another
  • Calculate aggregate values from JSON data
  • Filter and sort JSON arrays
  • Implement business logic in data processing pipelines

JSONata vs. Other Approaches

JSONata vs. JavaScript

While you can achieve similar results using JavaScript, JSONata offers several advantages:

  1. Conciseness: JSONata expressions are typically much shorter than equivalent JavaScript code
  2. Declarative style: Focus on what you want, not how to get it
  3. Safety: No risk of code injection or side effects
  4. Optimization: JSONata expressions can be optimized for performance

JSONata vs. jq

jq is another popular JSON processor:

  1. Integration: JSONata is designed to be embedded in JavaScript applications
  2. Learning curve: JSONata's syntax is often more intuitive for JavaScript developers
  3. Functionality: Both are powerful, but with different design philosophies

Getting Started with JSONata

To start using JSONata in your JavaScript or TypeScript project:

npm install jsonata

Basic usage:

JavaScript
const data = {
  customer: {
    name: "John Doe",
    orders: [
      { id: 1, item: "Laptop", price: 1200 },
      { id: 2, item: "Phone", price: 800 },
      { id: 3, item: "Tablet", price: 1500 }
    ]
  }
};

const expression = jsonata('customer.orders[price > 1000]');
const result = await expression.evaluate(data);  
console.log(result);

Basic Usage of JSONata

Basic Usage of JSONata

Use Cases for JSONata

1. API Response Transformation

When working with APIs that return more data than you need, JSONata can transform responses to match your application's requirements:

JavaScript
const apiResponse = {
    "records": [
      { "id": 1, "firstName": "John", "lastName": "Doe", "age": 28, "email": "john@example.com" },
      { "id": 2, "firstName": "Jane", "lastName": "Smith", "age": 32, "email": "jane@example.com" }
    ],
    "pagination": { "total": 200, "page": 1, "perPage": 2 }
  };
  
  // JSONata transformation
  const expression = jsonata(`{
    "users": records.{
      "fullName": firstName & " " & lastName,
      "contactInfo": {
        "email": email,
        "age": age
      }
    },
    "totalUsers": pagination.total
  }`);
  
  const result = await expression.evaluate(apiResponse);
  console.dir(result,{depth:null})

API Response Transformation with JSONata

API Response Transformation with JSONata

2. Data Aggregation and Analysis

JSONata excels at performing calculations on data:

JavaScript
const salesData = {
  "transactions": [
    { "category": "Electronics", "amount": 1200 },
    { "category": "Clothing", "amount": 90 },
    { "category": "Electronics", "amount": 500 },
    { "category": "Groceries", "amount": 125 }
  ]
};
// Simple aggregation example
const expression = jsonata(`{
  "total": $sum(transactions.amount),
  "average": $round($average(transactions.amount), 2),
  "categories": {
    "Electronics": $sum(transactions[category="Electronics"].amount),
    "Clothing": $sum(transactions[category="Clothing"].amount),
    "Groceries": $sum(transactions[category="Groceries"].amount)
  }
}`);
expression.evaluate(salesData)
  .then(result => console.log(JSON.stringify(result, null, 2)))
  .catch(err => console.error('Error:', err));

This example shows basic data aggregation: calculating totals, averages, and summing values by category.

Data Aggregation and Analysis with JSONata

Data Aggregation and Analysis with JSONata

3. Configuration Management

Use JSONata to customize configurations based on environments:

JavaScript
const baseConfig = {
    "app": {
      "name": "DevTools App",
      "environments": {
        "development": { "apiUrl": "http://localhost:3000/api", "debug": true },
        "staging": { "apiUrl": "https://staging-api.example.com", "debug": true },
        "production": { "apiUrl": "https://api.example.com", "debug": false }
      },
      "defaults": { "timeout": 5000, "retries": 3 }
    }
  };
  async function getConfig(env) {
    const expression = jsonata(`{
      "name": app.name,
      "apiUrl": app.environments.${env}.apiUrl,
      "debug": app.environments.${env}.debug,
      "timeout": app.defaults.timeout,
      "retries": app.defaults.retries
    }`);
    
    const result = await expression.evaluate(baseConfig);
    return result;
  }
  getConfig('development').then(result => console.log(result)).catch(error => console.error(error));
  getConfig('staging').then(result => console.log(result)).catch(error => console.error(error));
  getConfig('production').then(result => console.log(result)).catch(error => console.error(error));

Configuration Management with JSONata

Configuration Management with JSONata

Advanced JSONata Features

1. Custom Functions

JSONata allows you to define custom functions for reusable logic:

JavaScript
const apiResponse = {
    "order": {
        "items": [
            {"name": "Apple","price": 0.99,"quantity": 3},
            {"name": "Banana","price": 0.59,"quantity": 5},
            {"name": "Orange","price": 1.29,"quantity": 2}
        ]
    }
}
const expression = jsonata(`(
    $formatCurrency := function($amount) {
      "$" & $string($round($amount, 2))
    };
    {
      "items": order.items.{
        "product": name,
        "price": $formatCurrency(price),
        "total": $formatCurrency(price * quantity)
      },
      "orderTotal": $formatCurrency($sum(order.items.(price * quantity)))
    }
  )`);
try {
    const result = await expression.evaluate(apiResponse);
    console.dir(result, { depth: null, colors: true });
} catch (err) {
    console.error('JSONata evaluation failed:\n', err);
}

Custom Functions in JSONata

Custom Functions in JSONata

2. Error Handling

Handle missing or invalid data gracefully:

JavaScript
const apiResponse = {
  customer: {
    address: {}
  }
};
const expression = jsonata(
  `customer.address.zipCode ? customer.address.zipCode : "No ZIP code provided"`
);
try {
  const result = await expression.evaluate(apiResponse);
  console.dir(result, { depth: null, colors: true });
} catch (err) {
  console.error('JSONata evaluation failed:\n', err);
}

Error Handling in JSONata

Error Handling in JSONata

3. Recursive Processing

Process nested structures with recursive functions:

JavaScript
const apiResponse = {
    "rootNode": {
        "name": "root",
        "type": "folder",
        "children": [
            {"name": "file1.txt","type": "file","size": 123},
            {"name": "subfolder","type": "folder",
            "children": [{"name": "file2.txt","type": "file","size": 456}]
            }
        ]
    }
};
const expression = jsonata(`(
        $processNode := function($node) {
          $node.type = "folder" ? 
            {
              "name": $node.name,
              "type": "folder",
              "children": $node.children.$processNode($)
            } : 
            {
              "name": $node.name,
              "type": "file",
              "size": $node.size
            }
        };
        
        $processNode(rootNode)
      )`);
try {
    const result = await expression.evaluate(apiResponse);
    console.dir(result, { depth: null, colors: true });
} catch (err) {
    console.error('JSONata evaluation failed:\n', err);
}

Recursive Processing in JSONata

Recursive Processing in JSONata

Conclusion

JSONata offers a powerful yet elegant approach to querying and transforming JSON data. Its concise syntax, combined with rich functionality, makes it an excellent choice for handling JSON in modern applications. Whether you're processing API responses, transforming data structures, or implementing complex business logic, JSONata can significantly simplify your code while making it more maintainable.

For developers working with JSON data, adding JSONata to your toolkit is definitely worth the small investment in learning its syntax. The productivity gains and code clarity it provides will pay dividends as your applications grow in complexity.

JSONata
JSON
Data Transformation
Query Language
Development

Related Posts

JSON to XML Conversion: Complete Developer Guide 2025

Learn how to convert JSON to XML effectively with practical examples, best practices, and common pitfalls to avoid. Complete guide for developers working with data transformation.

By DevToolLab Team

Best Webhook.site Alternatives in 2025

Discover the best webhook.site alternatives for API testing and webhook debugging in 2025. From free tools to enterprise solutions.

By DevToolLab Team

Essential Developer Tools Every Programmer Needs in 2025

Discover the must-have developer tools for 2025 that will boost your productivity, streamline your workflow, and make coding more efficient. From code formatters to API testing tools.

By DevToolLab Team