JSON Transform Rules
Paste JSON plus mapping rules, then reshape it into a new object or patch/redact the original. Supports shorthand rules, JSON rule objects, JSONPath-style selectors, defaults, transforms, per-item mapping, and rule reports.
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": "[email protected]"},
"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": "[email protected]",
"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
eachcan 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. Usewhenfor simple truthy guards and transforms such assum,count,first,join,upper,trim,keys, andvaluesfor common reshaping steps. mode = buildstarts with an empty object.mode = mergestarts with a copy of the input, so-pathshorthand orop = "remove"can redact fields.on_missing = skipomits missing targets,nullwritesnull, anderrorstops on the first missing selector. A rule-leveldefaultoverrides all three.array_mode = autoreturns a scalar for one match and an array for many matches. Choosealwaysfor stable array shapes orfirstwhen only the first value should survive.- Target array indexes are capped at 10,000 to catch accidental sparse-array writes like
items[999999].
FAQ
Is this a full JSONPath implementation?
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.
When should I use build mode versus merge mode?
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.
How do I map every item in an array?
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.
What happens when a selector matches more than one value?
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.
Is my JSON uploaded anywhere?
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.
Developer & Automation Access
Run it from the terminal
Same engine as this page, headless — via the gizza CLI:
gizza tool json-transform-rules '{
"user": {"id": 7, "name": " Ada Lovelace ", "email": "[email protected]"},
"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"'New to the CLI? Get gizza →
Open it by URL
Pre-fill and auto-run this tool with query parameters — the names match the API/CLI:
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=jsonMachine-readable descriptor: tool.json — title + parameters JSON Schema for agents.
