Documentation

Learn JSONFiddle by workflow

Short guides for viewing, querying, editing, converting, and exporting structured data in the browser.

Query and Transform JSON

The Query view is JSONFiddle's data extraction and transformation engine. Write expressions to pull specific values from your JSON, reshape the data, compute aggregations, and apply the result back to your source document.

Switch to the Query view by clicking "Query" in the view selector or pressing Alt+4.


Prerequisites

  • Valid JSON, YAML, XML, or CSV content in the editor (the Query view is disabled for Mermaid and JFDG formats).
  • Basic familiarity with path expressions. If you have used XPath, CSS selectors, or SQL, the concepts are similar.

Three Query Languages

Use the segmented control at the top of the Query tab to switch between them.

LanguageBest ForSyntax StyleExample
JSONPathSimple path extraction, familiar to XPath users$.path.to.value$.store.book[*].title
JQComplex filtering, piping, chaining transforms.path | filter | transform.store.book[] | select(.price < 10)
JSONataDeclarative mapping, aggregation, functional transformspath.subpath$sum(Account.Order.Product.Price)

Tip: Start with JSONPath for simple extractions, JQ for filtering and piping, and JSONata for aggregations and restructuring.

Which Language for Which Task?

TaskJSONPathJQJSONataRecommendation
Get a value by pathYesYesYesAny.
Filter by conditionLimitedBestGoodJQ for complex filters.
Count itemsNoYesBestJSONata has native $count().
Sum / Average / Min / MaxNoYesBestJSONata has native aggregation functions.
Reshape / restructureNoBestGoodJQ for piped transformations.
String manipulationNoYesYesBoth JQ and JSONata support string ops.
Recursive descent (search all levels)BestYesYesJSONPath's .. operator is simplest.
Extract unique valuesNoYesYesJQ's unique or JSONata's $distinct().

Running a Query

  1. Switch to the Query tab (Alt+4).
  2. Select your query language (JSONPath, JQ, or JSONata).
  3. Type your expression in the query input field.
  4. Press Cmd+Enter (Mac) or Ctrl+Enter (Windows/Linux), or click the play button.
  5. The result appears below the query bar as formatted JSON.

Tip: Press Tab to accept an autocomplete suggestion, or Ctrl+Space to open the autocomplete widget.


Smart Placeholder Queries

When you place your cursor on a specific value in the code editor, JSONFiddle automatically generates a query expression targeting that value. The placeholder text in the query input updates in real time as you move your cursor.

Smart placeholder Screenshot: The Query tab showing a smart placeholder expression based on cursor position.

  1. Click on any value in the code editor.
  2. Switch to the Query tab.
  3. The query input's placeholder shows the path to the value at your cursor.
  4. Click the placeholder (or press Enter with an empty input) to use it.

Data-Aware Help

The helper text and example chips are generated from the current document and selected query language. JSONFiddle looks at the fields, arrays, primitive values, and cursor path in your content, then offers examples that fit the data you actually pasted.

For example:

  • JSONPath examples start from $ and target real paths in the current JSON.
  • JQ examples use dot paths and pipes that match current arrays or objects.
  • JSONata examples use field paths and aggregation functions for detected arrays and numbers.
  • SQL examples are available from the SQL on JSON tool when your data is more table-like.

If a pasted document is very small or irregular, the suggestions stay conservative so they do not invent fields that are not present.


Transform Suggestion Chips

Below the query bar, JSONFiddle displays type-aware suggestion chips -- small buttons suggesting common operations based on the data type of the current result or cursor path.

Array Suggestions

ChipWhat it Does
LengthCounts the number of elements.
FirstExtracts the first element.
LastExtracts the last element.
SortSorts the array.
FlattenFlattens nested arrays.
UniqueRemoves duplicate values.
ReverseReverses the order of elements.

String Suggestions

ChipWhat it Does
LengthReturns the string's character count.
UppercaseConverts to uppercase.
LowercaseConverts to lowercase.
SplitSplits the string into an array by a delimiter.

Number Suggestions

ChipWhat it Does
SumSums all values.
AverageCalculates the mean.
Min / MaxFinds the smallest or largest value.

Clicking a suggestion chip Screenshot: The Query tab showing type-aware suggestion chips below the query bar.

Click any chip to populate the query input and run it automatically.


The Transform Workflow

Write -> Run -> Preview -> Apply -> (optionally) Revert.

Step 1: Write and Run

Type your expression and press Cmd+Enter. The result panel shows the output.

Step 2: Preview the Result

Review the output. Modify the query and run again if needed.

Step 3: Apply

Click Apply to replace the source JSON in the editor with the query result.

Step 4: Revert

Click Revert to restore the previous content. JSONFiddle keeps one level of undo for applied transformations.

Original JSON --[Run Query]--> Result Preview --[Apply]--> Updated JSON
                                                              |
                                                        [Revert] --> Original JSON

Warning: Applying replaces the entire editor content. If you apply and then make more edits, Revert restores to the pre-apply state, not to the latest edits.


Copy As: Get Any Node's Path

In the Graph, Explorer, and Grid views, right-click any node, row, or cell to access the Copy As submenu.

Copy As OptionExample Output
Copy as JSONPath$.users[0].name
Copy as JQ.users[0].name
Copy as JSONatausers[0].name
Copy as XPath/users/0/name

Paste the copied expression directly into the Query tab's input field.

Copy As context menu Screenshot: The Graph view context menu with Copy As options.


"Transform This..." Action

Right-click a node, row, or cell in any visual view, then click Transform this.... JSONFiddle switches to the Query tab with the path pre-filled.


JSONPath Reference (10+ Examples)

JSONPath uses a $.path.to.value syntax similar to XPath. The root is $.

Sample Data

All examples use this JSON:

{
  "store": {
    "name": "Book Haven",
    "books": [
      { "title": "The Great Gatsby", "author": "Fitzgerald", "price": 12.99, "genre": "fiction", "in_stock": true },
      { "title": "Clean Code", "author": "Martin", "price": 35.99, "genre": "technical", "in_stock": true },
      { "title": "1984", "author": "Orwell", "price": 9.99, "genre": "fiction", "in_stock": false },
      { "title": "Design Patterns", "author": "GoF", "price": 45.00, "genre": "technical", "in_stock": true },
      { "title": "The Hobbit", "author": "Tolkien", "price": 14.99, "genre": "fiction", "in_stock": true }
    ],
    "location": {
      "city": "Portland",
      "state": "OR",
      "zip": "97201"
    }
  }
}

Examples

#ExpressionResultExplanation
1$.store.name"Book Haven"Get a single value by path.
2$.store.books[0]{ "title": "The Great Gatsby", ... }Get the first array element (0-indexed).
3$.store.books[*].title["The Great Gatsby", "Clean Code", "1984", ...]Get all titles from the array.
4$.store.books[-1].title"The Hobbit"Get the last element using negative index.
5$.store.books[0:2]First two booksArray slice (start inclusive, end exclusive).
6$.store.books[?(@.genre=="fiction")]Three fiction booksFilter by condition.
7$.store.books[?(@.price<15)]Books under $15Numeric comparison filter.
8$.store.books[?(@.in_stock==true)].titleTitles of in-stock booksChained filter + extract.
9$..authorAll author values (recursive)Recursive descent.
10$..priceAll price valuesRecursive descent for prices.
11$.store.books.length5Array length.
12$.store.location.*["Portland", "OR", "97201"]All values of an object.

JQ Reference (10+ Examples)

JQ uses a piped filter syntax. The root is . (dot).

Examples (same sample data)

#ExpressionResultExplanation
1.store.name"Book Haven"Get a single value.
2.store.books[0]First book objectGet by index.
3.store.books[].titleAll titles (streamed)Iterate and extract.
4[.store.books[].title]["The Great Gatsby", ...]Wrap in array.
5.store.books[] | select(.genre == "fiction")Fiction booksFilter with select().
6.store.books[] | select(.price < 15) | .titleTitles of cheap booksChained pipe.
7.store.books | length5Array length.
8[.store.books[].price] | add118.96Sum all prices.
9[.store.books[].price] | add / length23.792Average price.
10[.store.books[].price] | min9.99Minimum price.
11.store.books | sort_by(.price)Books sorted by priceSort an array of objects.
12.store.books | sort_by(.price) | reverseExpensive firstSort descending.
13[.store.books[] | select(.in_stock) | {title, price}]Array of {title, price} for in-stockReshape while filtering.
14.store.books | group_by(.genre) | map({genre: .[0].genre, count: length})Count by genreGroup and aggregate.
15[.store.books[].genre] | unique["fiction", "technical"]Distinct values.

JSONata Reference (10+ Examples)

JSONata uses a declarative, XPath-like syntax with built-in functions.

Examples (same sample data)

#ExpressionResultExplanation
1store.name"Book Haven"Get a single value (no $ prefix needed).
2store.books[0]First bookGet by index.
3store.books.title["The Great Gatsby", ...]Extract all titles.
4store.books[genre = "fiction"]Fiction booksFilter by condition.
5store.books[price < 15].titleTitles of cheap booksFilter + extract.
6$count(store.books)5Count items.
7$sum(store.books.price)118.96Sum values.
8$average(store.books.price)23.792Average value.
9$min(store.books.price)9.99Minimum.
10$max(store.books.price)45.00Maximum.
11store.books^(price)Books sorted by price ascendingSort operator.
12store.books^(>price)Books sorted by price descendingSort descending.
13store.books{genre: $count($)}{"fiction": 3, "technical": 2}Group and count.
14$distinct(store.books.genre)["fiction", "technical"]Unique values.
15{ "total": $sum(store.books.price), "avg": $average(store.books.price), "count": $count(store.books) }Summary objectBuild a new structure.

Cookbook: 15+ Real-World Recipes

Recipe 1: Extract All Emails from a Nested API Response

Input:

{
  "data": {
    "departments": [
      { "name": "Sales", "members": [
        { "name": "Alice", "email": "alice@acme.com" },
        { "name": "Bob", "email": "bob@acme.com" }
      ]},
      { "name": "Engineering", "members": [
        { "name": "Charlie", "email": "charlie@acme.com" }
      ]}
    ]
  }
}
LanguageExpression
JSONPath$..email
JQ[.. | .email? // empty]
JSONatadata.departments.members.email

Output: ["alice@acme.com", "bob@acme.com", "charlie@acme.com"]


Recipe 2: Filter Users by Role

LanguageExpression
JSONPath$.users[?(@.role=="admin")]
JQ[.users[] | select(.role == "admin")]
JSONatausers[role = "admin"]

Recipe 3: Rename All Keys (JQ)

Transform { "first_name": "Alice" } to { "firstName": "Alice" }:

.users[] | { firstName: .first_name, lastName: .last_name, emailAddress: .email }

Recipe 4: Flatten a Nested Structure (JSONata)

data.departments.{
  "department": name,
  "members": members.name
}

Recipe 5: Count Items by Category

LanguageExpression
JQgroup_by(.category) | map({category: .[0].category, count: length})
JSONata$each($reduce(products, function($acc, $item) { $merge([$acc, {($item.category): ($lookup($acc, $item.category) + 1)}]) }, {}), function($v, $k) { {"category": $k, "count": $v} })

Recipe 6: Calculate Statistics (Sum, Average, Min, Max)

StatisticJQJSONata
Sum[.items[].price] | add$sum(items.price)
Average[.items[].price] | add / length$average(items.price)
Min[.items[].price] | min$min(items.price)
Max[.items[].price] | max$max(items.price)

Recipe 7: Merge Two Arrays (JQ)

.array1 + .array2 | unique_by(.id)

Recipe 8: Remove Null Values (JQ)

walk(if type == "object" then with_entries(select(.value != null)) else . end)

Recipe 9: Transform API Response to a Different Shape

Input:

{ "data": { "users": [{ "id": 1, "attributes": { "name": "Alice", "email": "alice@example.com" }}]}}

JQ:

[.data.users[] | { id, name: .attributes.name, email: .attributes.email }]

JSONata:

data.users.{ "id": id, "name": attributes.name, "email": attributes.email }

Recipe 10: Extract Unique Values

LanguageExpression
JQ[.items[].category] | unique
JSONata$distinct(items.category)

Recipe 11: Conditional Value Mapping (JSONata)

Add a "tier" field based on price:

products.(
  $ ~> | $ | { "tier": price > 100 ? "premium" : price > 50 ? "standard" : "budget" } |
)

Recipe 12: Nested Object to Flat Key-Value Pairs (JQ)

[to_entries[] | { key, value: (.value | tostring) }]

Recipe 13: Date Filtering (JQ)

Filter items created after a specific date:

[.events[] | select(.created_at > "2024-01-01")]

Recipe 14: Pivot a Table (JSONata)

{
  "months": $distinct(sales.month),
  "data": $distinct(sales.product).(
    $product := $;
    { "product": $product, "values": $$.sales[product = $product].amount }
  )
}

Recipe 15: Extract All Leaf Values (JQ)

[.. | scalars]

Debugging Queries

Common Errors and Fixes

ErrorCauseFix
"No match"The path does not existCheck for typos; use Copy As to get the correct path.
"Unexpected token"Syntax error in the expressionCheck parentheses, brackets, and quotes.
"Cannot iterate over null"Intermediate path resolves to nullAdd a null check: .field? // empty (JQ).
Empty result []Filter matches nothingLoosen the filter condition or check the field name.

Debugging Strategies

  1. Start simple. Begin with the root path (. in JQ, $ in JSONPath) and add one path segment at a time.
  2. Use Copy As. Right-click a node in the Graph view and copy its path -- this guarantees accuracy.
  3. Check the type. If you expect an array but get an object, add [] to iterate.
  4. Inspect the placeholder. The smart placeholder shows what JSONFiddle thinks the path is at your cursor.

Debugging a query Screenshot: The Query tab showing a JSONPath result in the output panel.


Troubleshooting

"The Query tab is disabled"

The Query view is not available for Mermaid or JFDG formats. Switch to JSON, YAML, XML, or CSV.

"My query runs but returns nothing"

Check if the path exists in your data. Use the Graph or Explorer view to verify. JSONPath returns undefined if the path is invalid; JQ returns nothing; JSONata returns undefined.

"The Apply button does nothing"

Run the query first (Cmd+Enter), then click Apply.

"I applied a transformation and lost my original data"

Click Revert to restore the pre-apply content. If you have already made additional edits after applying, those post-apply edits are lost.


FAQ

Q: Can I use regular expressions in queries? A: JQ supports regex with test() and capture(). JSONata supports $match(). JSONPath has limited regex support with the =~ operator.

Q: Can I query YAML or XML data? A: Yes. JSONFiddle reads YAML and XML as structured data first, so queries run against the same shape you see in the visual views.

Q: How large can the data be before queries get slow? A: JSONPath and JQ handle millions of rows efficiently. JSONata can be slower on very large datasets.

Q: Can I chain multiple queries? A: In JQ, yes -- use pipes (|). In JSONata, yes -- use nested expressions. In JSONPath, no.


  • Getting Started -- overview of the editor and all four views.
  • Keyboard Shortcuts -- Query tab shortcuts (Cmd+Enter, Tab, Ctrl+Space).
  • Graph View -- Copy As and Transform this... from the graph context menu.
  • Grid View -- Copy As and Transform this... from grid rows.
  • Explorer View -- Copy As and Transform this... from the explorer context menu.