# JSON Transform Rules

Reshape JSON with declarative target = selector rules, JSONPath-style selectors, defaults, transforms, merge mode, and a rule report.

## Run it

- **CLI:** `gizza tool json-transform-rules '{
  "user": {"id": 7, "name": " Ada Lovelace ", "email": "ada@example.com"},
  "orders": [{"total": 19.5}, {"total": 30.5}],
  "ssn": "000-00-0000"
}' 'rules=id = $.user.id
name = $.user.name
email = $.user.email
total = $..total
source = "import"'`
- **Web:** https://gizza.ai/tools/json-transform-rules/
- **Agents:** machine-readable descriptor (parameters JSON Schema) at https://gizza.ai/tools/json-transform-rules/tool.json

## Inputs

- `json` — Source JSON _(field)_
- `rules` — Transform rules _(field)_
- `each` — Each selector (blank = whole document) _(field)_
- `mode` — Output mode _(field)_
- `on_missing` — Missing selector behavior _(field)_
- `array_mode` — Multi-match output _(field)_
- `pretty` — Pretty-print JSON _(field)_
- `indent` — Indent spaces _(field)_
- `output` — Output _(field)_

## Output

- Transformed JSON (text)

## Query parameters

Open the tool pre-filled and auto-run via URL:

- `json` — Source JSON
- `rules` — Transform rules
- `each` — Each selector (blank = whole document)
- `mode` — Output mode
- `on_missing` — Missing selector behavior
- `array_mode` — Multi-match output
- `pretty` — Pretty-print JSON
- `indent` — Indent spaces
- `output` — Output

Example: `https://gizza.ai/tools/json-transform-rules/?json=%7B%0A%20%20%22user%22%3A%20%7B%22id%22%3A%207%2C%20%22name%22%3A%20%22%20Ada%20Lovelace%20%22%2C%20%22email%22%3A%20%22ada%40example.com%22%7D%2C%0A%20%20%22orders%22%3A%20%5B%7B%22total%22%3A%2019.5%7D%2C%20%7B%22total%22%3A%2030.5%7D%5D%2C%0A%20%20%22ssn%22%3A%20%22000-00-0000%22%0A%7D&rules=id%20%3D%20%24.user.id%0Aname%20%3D%20%24.user.name%0Aemail%20%3D%20%24.user.email%0Atotal%20%3D%20%24..total%0Asource%20%3D%20%22import%22&each=%24.orders%5B%2A%5D&mode=build&on_missing=skip&array_mode=auto&pretty=true&indent=2&output=json`

---

## About this tool

JSON Transform Rules reshapes a JSON document with a small declarative rule list. Each rule names an output target path and where its value comes from: a JSONPath-style selector, a literal value, or a removal operation in merge mode. It is useful when you need to normalize an API response, build a smaller payload for another system, redact fields before sharing a sample, or debug how a mapping will behave before you put it in code.

The shorthand form is designed for quick work:

```
id = $.user.id
name = $.user.name
email = $.user.contact.email
source = "import"
```

For larger mappings, paste a JSON object of `target -> selector` pairs or a JSON array of rule objects with `target`, `source`, `value`, `default`, `transform`, `separator`, `when`, and `op`. Selectors support `$`, `.key`, `["key"]`, `[0]`, `[*]`, `.*`, and `..key`. Target paths use dot and bracket notation, create missing objects and arrays, and can append with `tags[]`.

Worked example — map a nested API response into a flatter payload:

Source JSON:

```
{
  "user": {"id": 7, "name": "Ada Lovelace", "email": "ada@example.com"},
  "orders": [{"total": 19.5}, {"total": 30.5}]
}
```

Rules:

```
id = $.user.id
name = $.user.name
email = $.user.email
total = $..total
source = "import"
```

Output:

```
{
  "id": 7,
  "name": "Ada Lovelace",
  "email": "ada@example.com",
  "total": [
    19.5,
    30.5
  ],
  "source": "import"
}
```

Use **Each selector** when one input array should become one output object per item. For example, set `each` to `$.automobiles[*]`, then rules like `title = $.model` and `year = $.year` run against every automobile and return an array of mapped objects. Use **Output → Rule match report** when a mapping comes out empty; it shows which rules matched, wrote, skipped, or used defaults.

## Limits and edge cases

- Source JSON is capped at **5 MB**, rules at **200 KB**, and one run at **500 rules**. A selector can match at most **100,000 values**, and `each` can fan out over at most **50,000 items**.
- This is a JSONPath subset, not a full query language. Filters such as `[?(@.price > 10)]`, slices, arithmetic expressions, and script callbacks are intentionally out of scope. Use `when` for simple truthy guards and transforms such as `sum`, `count`, `first`, `join`, `upper`, `trim`, `keys`, and `values` for common reshaping steps.
- `mode = build` starts with an empty object. `mode = merge` starts with a copy of the input, so `-path` shorthand or `op = "remove"` can redact fields.
- `on_missing = skip` omits missing targets, `null` writes `null`, and `error` stops on the first missing selector. A rule-level `default` overrides all three.
- `array_mode = auto` returns a scalar for one match and an array for many matches. Choose `always` for stable array shapes or `first` when only the first value should survive.
- Target array indexes are capped at **10,000** to catch accidental sparse-array writes like `items[999999]`.

## FAQ

<details>
<summary>Is this a full JSONPath implementation?</summary>

No. It supports the selector pieces that are safe and predictable inside this tool: root `$`, dotted keys, quoted keys, array indexes, wildcards, and recursive descent by key. It does not implement filter predicates, slices, unions, or embedded scripts. That keeps the mapping portable across the browser, CLI, and sandboxed chat runtime.

</details>

<details>
<summary>When should I use build mode versus merge mode?</summary>

Use **build** when you want a fresh output object containing only the fields named by the rules. Use **merge** when you want to patch or redact the original document: the output starts as a copy of the input, then rules overwrite paths and `-path` rules remove paths such as `-ssn` or `-debug.trace`.

</details>

<details>
<summary>How do I map every item in an array?</summary>

Put the array selector in **Each selector**, for example `$.items[*]`. The rules then run with each item as their local root, so `sku = $.sku` and `price = $.price` produce one output object per item. Leave **Each selector** blank when all rules should run once against the whole source document.

</details>

<details>
<summary>What happens when a selector matches more than one value?</summary>

With the default **auto** mode, one match becomes a scalar and multiple matches become an array. Select **Always arrays** when downstream code needs a stable array shape, or **First match only** when a selector can match many values but only the first should be kept. Aggregate transforms such as `sum`, `count`, `min`, `max`, `avg`, and `join` return one value after aggregating the matches.

</details>

<details>
<summary>Is my JSON uploaded anywhere?</summary>

No. The tool runs locally in WebAssembly in the browser page, and the same core runs in the command line and sandboxed chat block. Your pasted JSON and rules are not sent to a server by this page.

</details>

## Related tools

- [Query & transform JSON with JSONata](https://gizza.ai/tools/jsonata-query/): Run a JSONata expression against any JSON document right in your browser — query, filter, aggregate, and reshape JSON. Pure-Rust engine, nothing is uploaded, free.
- [JSONPath Query](https://gizza.ai/tools/jsonpath-query/): Evaluate JSONPath expressions (RFC 9535) against any JSON in your browser — wildcards, slices, recursive descent, filters. Free, private, nothing uploaded.
- [Absolute value, sign, or negation for a whole column](https://gizza.ai/tools/absolute-value-transformer/): Paste a column of numbers and apply absolute value, sign extraction (-1/0/1), sign flipping, or force-negative to every value at once, with rounding and an audit table.
- [Adjacency Matrix Converter](https://gizza.ai/tools/adjacency-matrix-converter/): Convert a graph between edge list, adjacency matrix, and incidence matrix — directed or undirected, weighted or not. Free, private, runs in your browser.
- [Amazon Order Analyzer](https://gizza.ai/tools/amazon-order-analyzer/): Paste an Amazon order-history CSV export to summarize total spend by month, top items, and category breakdowns. Browser-only, private, with Markdown or JSON output.
