JSON Query & Transform Tool

Load or paste JSON data and test queries.

JSON Query Language Specification

A lightweight, JavaScript-native syntax for deep traversal, mutation, filtering, and aggregation of JSON data. Queries are evaluated strictly left-to-right.

Core Philosophy: Path extraction happens first, followed by filtering {condition} , projection/shaping => {shape}, and finally modifiers :modifier . Weak typing applies implicitly (e.g., "3" <= 3 evaluates to true).

1. Data Context Reference

All examples in this documentation are executed against the following JSON dataset:

{
  "total_count": 3,
  "users": [
    { 
      "id": 101, "name": "Alice Vance", "age": 28, "str_id": "3", "is_admin": true, 
      "tags": ["frontend", "ux", "mentor"], "address": {"city": "Berlin", "country": "Germany"}, "deleted_at": null 
    },
    { 
      "id": 102, "name": "Bob Smith", "age": 34, "is_admin": false, 
      "tags": ["backend", "devops"], "secret_identity": "Bernd Schmitt", 
      "address": {"city": "San Francisco", "country": "USA"}, "deleted_at": "2025-12-01" 
    },
    { 
      "id": 103, "name": "Charlie Day", "age": 40, "is_admin": false, 
      "tags": ["manager"], "address": {"city": "Berlin", "country": "Germany"}, "deleted_at": null 
    }
  ],
  "active_status": true,
  "metadata": { "version": 1.2 }
}

2. Basic Extraction & Traversal

Use dot notation (or implicit paths) to extract nodes. If applied to an array, the language automatically maps the path extraction across all items in the array.

Query String Result / Explanation
active_status
true
Fetches root-level primitives.
metadata.version
1.2
Traverses objects.
users.name
["Alice Vance", "Bob Smith", "Charlie Day"]
Auto-maps extraction across arrays.
users.secret_identity
[undefined, "Bernd Schmitt", undefined]
Missing properties safely return native undefined.
users[0].name
Alice Vance
You can access array elements by index.
users[-1].name[0]
C
Use -1 for getting the last element. Strings can also be indexed.
users[0:2].name
["Alice Vance", "Bob Smith"]
Python-style slicing. Returns elements from start (inclusive) to end (exclusive).
users[1:]
users[:-1]
users[-2:]
Open slices. Omit start or end to slice from the beginning or to the end. Negative indices count from the end.
users[-1].name[0:3]
Cha
Slicing works on strings too.

3. Filtering Data

Encapsulate conditions inside braces {}. The syntax maps closely to JS operators but introduces cleaner query aliases.

Query String Result / Explanation
users.{address.city == 'Berlin'}.name
users{address.city == 'Berlin'}name
["Alice Vance", "Charlie Day"]
Filters array based on deep boolean evaluations. Note that the . before and after braces is optional.
users.{age < 40 and not is_admin}.name
["Bob Smith"]
Compound logic operators.
users.{deleted_at == null}.id
[101, 103]
Null comparisons.
users.{has secret_identity}.name
users.{secret_identity != undefined}.name
["Bob Smith"]
has verifies property existence. Standard undefined checks also work.
users.{'ux' in tags}.id
users.{tags contains "ux"}.id
[101]
in and contains act as safe array-inclusion lookups. Both syntaxes act as identical synonyms.
users.{str_id <= 3}.name
["Alice Vance"]
Demonstrates implicit JS weak-typing. String "3" is evaluated successfully against Integer 3.
users.{name =~ /^B/}.id
[102]
The =~ operator invokes native JavaScript RegExp pattern matching.
users.{name !~ /^A/}.name
["Bob Smith", "Charlie Day"]
The !~ operator negates the regex match. Supports flags like /pattern/i.
users{tags:len < 3}.id
[102, 103]
You can also use modifiers in conditions.

4. Projection & Shape Mutation

Use the fat arrow => {} to remap existing objects into entirely new structures. You can map variables directly, inject hardcoded strings, or use spread syntax to control field inheritance.

Query String Result / Explanation
=> {last_updated, meta: metadata}
{
  "last_updated": "2026-02-16T18:00:00Z",
  "meta": {
    "version": 1.2,
    "environment": "production"
  }
}
Project whole input to a new structure with only last_updated and metadata (renaming metadata to meta).
users => {id: id}
users => {id}
[{"id": 101}, {"id": 102}, {"id": 103}]
Standard key/value mapping.
users => {name: "test"}
[{"name": "test"}, {"name": "test"}, {"name": "test"}]
Supports injection of hardcoded literals.
users.{age < 40} => {first_name: name, location: address.city}
[
  {"first_name": "Alice Vance", "location": "Berlin"}, 
  {"first_name": "Bob Smith", "location": "San Francisco"}
]
Shape mapping with nested resolution.
users.{id == 101} => {first_name: name, ... but name, is_admin, address}
[
  {
    "first_name": "Alice Vance", 
    "id": 101, 
    "age": 28, 
    "str_id": "3", 
    "tags": ["frontend", "ux", "mentor"], 
    "deleted_at": null
  }
]
Use ... to spread the original object properties. Use ... but field, field to blacklist specific fields from the spread operation.

5. Array Manipulation

Modifiers (prefixed by :) alter structural boundaries, limits, and array definitions.

Query String Result / Explanation
users.tags
[["frontend", "ux", "mentor"], ["backend", "devops"], ["manager"]]
Standard traversal maintains 2D structural boundaries.
users.tags:flat
["frontend", "ux", "mentor", "backend", "devops", "manager"]
:flat destroys 1 level of inner-array boundaries.
users.address.city:unique
["Berlin", "San Francisco"]
Deduplicates elements.
users.tags:flat:join(', ')
"frontend, ux, backend, devops, manager"
Chains modifiers to collapse an array into a single concatenated string.
users:limit(1).name
["Alice Vance"]
Truncates arrays.
users:len
users.name:len
3
Returns counts of arrays
users[0]:len
8
... or count of object keys.
users:reverse.name
["Charlie Day", "Bob Smith", "Alice Vance"]
:reverse reverses array order without mutating.

6. Aggregations, Grouping & Sorting

Query String Result / Explanation
users.age:avg
34
users.age:max
40
users.age:sum
102
Math modifiers apply calculations against evaluated arrays.
users:sort(age, desc).name
["Charlie Day", "Bob Smith", "Alice Vance"]
Accepts a sort target and an optional direction (asc / desc).
users:group_by(address.country)
{
  "Germany": [
    {"id": 101, "name": "Alice Vance", ...}, 
    {"id": 103, "name": "Charlie Day", ...}
  ], 
  "USA": [
    {"id": 102, "name": "Bob Smith", ...}
  ]
}
Pivots flat arrays into key-value objects based on deep-object values.
users => {name, city: address.city}:group_by(city)
{
  "Berlin": [
    {
      "name": "Alice Vance",
      "city": "Berlin"
    },
    {
      "name": "Charlie Day",
      "city": "Berlin"
    }
  ],
  "San Francisco": [
    {
      "name": "Bob Smith",
      "city": "San Francisco"
    }
  ]
}
First project the users to a new structure with only name and city, and then group by city.
users:count_by(address.country)
{"Germany": 2, "USA": 1}
Like :group_by, but returns counts per group instead of arrays.
users:group_by(address.country):keys
["Germany", "USA"]
:keys extracts object keys as an array. Useful after :group_by.
users:group_by(address.country):values Returns the grouped arrays. :values extracts object values as an array.
users:group_by(address.country):entries
[{"key": "Germany", "value": [...]}, {"key": "USA", "value": [...]}]
:entries converts an object into an array of {key, value} pairs, bridging object results back into array processing.

7. String Modifiers

String modifiers transform text values. When applied to an array, they auto-map over each element.

Query String Result / Explanation
users.name:upper
["ALICE VANCE", "BOB SMITH", "CHARLIE DAY"]
Converts strings to uppercase.
users.name:lower
["alice vance", "bob smith", "charlie day"]
Converts strings to lowercase.
name:lower:trim Modifiers can be chained. :trim removes leading and trailing whitespace.
users.{name:upper == 'BOB SMITH'}.id
[102]
String modifiers also work inline within filters.

8. Composition (Multi-Queries)

Query String Result / Explanation
{total: users:len, hired: users.{tags contains 'ux'}.name}
{
  "total": 3,
  "hired": [
    "Alice Vance"
  ]
}
Each value of the result object is computed as a separate query.
{total: `users`:len, "hired users": `users`.{tags contains 'ux'}.name}
{
  "total": 3,
  "hired users": [
    "Alice Vance"
  ]
}
You can use string syntax (double or single quotes) for aliases to include spaces and special characters. Arbitrary JSON field names that include special characters or spaces can be wrapped in backticks.
{`all tags`: users.tags:flat, users: `users`.{`tags`:len > 1} => {`user:id` : id}}
{
  "all tags": [
    "frontend",
    "ux",
    "mentor",
    "backend",
    "devops",
    "manager"
  ],
  "users": [
    {
      "user:id": 101
    },
    {
      "user:id": 102
    }
  ]
}