JSON in WordPress: REST API debugging, ACF schemas, theme.json — with one tool.
Modern WordPress is full of JSON. theme.json, block.json, ACF flexible-content schemas, REST API responses, transients, custom-post-type registrations, Gutenberg block attributes. Most WP devs end up flipping between three tools to inspect any of it. jsonyo is a small free utility — WordPress plugin, browser extension, and npm CLI — that handles the five jobs that 90% of JSON debugging boils down to: format, validate, query, diff, stats. Zero data leaves your browser. Free forever, no paid tier.
Why "another JSON tool"
The complaint isn't that JSON formatters don't exist — there are dozens online. The complaint is more specific:
- Online formatters mean copy-paste round-trips. wp-admin → tab to jsonformatter.org → paste → copy → tab back. For multi-step debugging (validate → format → query → diff) that's a lot of tab-flipping.
- Browser-extension JSON viewers don't query. They pretty-print and that's it. JSONPath / recursive descent is missing.
- Most online tools also collect telemetry, which matters when the JSON is a private REST response or a customer's ACF schema.
- WordPress-side, there's no native viewer. Looking at
theme.jsonmeans opening it in a code editor; looking at a transient means doingget_option('_transient_X')in WP-CLI.
jsonyo lives where you already work. The WP plugin lands at Tools → JSON Toolkit. The browser extension is one click in the toolbar. The npm CLI is one binary. Same engine, same syntax, byte-identical output.
The five modes
1. Format
Paste raw JSON. Get a properly indented tree with key / string / number / boolean syntax highlighting. Invalid input shows the exact line and column where the parser tripped — which matters when you're staring at a 600-line theme.json and the error is just "unexpected token at position 14782."
2. Validate
Pass or fail, plus a stats summary: total keys, max nesting depth, count of types. Useful as a sanity check before committing a theme.json change or before pushing an updated ACF JSON sync export.
3. Query (JSONPath)
The mode that handles 80% of REST API debugging:
$.posts[0].title.rendered // first post's rendered title
items[*].id // all item ids in an array
$..acf.flexible_content // recursive descent — matches at any depth
$.settings.color.palette[?].slug // wildcards work in arrays
jsonyo implements the practical subset: index access, array wildcards, and recursive descent (the .. operator). Filter expressions like [?(@.x>1)] are outside scope for an in-browser tool — if you need those, the npm CLI has a jsonyo query --js mode that takes a JS expression instead.
4. Diff
Paste two JSON blocks side-by-side. The output shows added paths, removed paths, and changed values, all in $.path notation. Useful for:
- Comparing two REST API responses across versions
- Diffing
theme.jsonbefore and after a global-styles change - Catching ACF flexible-content schema drift between staging and production
- Comparing transient values across cache busts
5. Stats
Counts of objects / arrays / strings / numbers / booleans / nulls / keys, plus max nesting depth. Quietly useful for sizing storage, reasoning about cache-key budgets, and guessing whether a payload will fit inside wp_options without bumping longtext truncation.
Three concrete WordPress workflows
Workflow A — REST API response inspection
Hit yoursite.com/wp-json/wp/v2/posts?per_page=5 in your browser. View source. Select all → copy. Paste into jsonyo. Pick format first to make it readable, then query with $..title.rendered to extract just the rendered titles, or $..acf to pull every ACF block in the response. Total time: 6 seconds, no tab-flipping.
Workflow B — ACF flexible-content schema audit
Export your ACF Field Group as JSON (Custom Fields → Tools → Export JSON). Open the file. Paste into jsonyo. Run validate to confirm structure. Run stats to see how many sub-fields are nested in the flexible-content block (above ~12, you should consider splitting). Run query with $..type to list every field type used — handy for finding stragglers like a single wysiwyg field where you meant textarea.
Workflow C — theme.json diff before merge
Copy theme.json from main. Copy the modified version from your branch. Paste both into jsonyo's diff mode. Get a path-by-path diff of color palette changes, font-family additions, block style edits. Catch the moment when a teammate accidentally redefined --wp--preset--color--primary globally instead of scoped to one block.
Why the WP plugin and the browser extension exist as separate things
Reasonable question. The answer is workflow scope:
| Surface | Best for | Worst for |
|---|---|---|
| WP plugin | Working inside wp-admin: debugging ACF schemas, theme.json, block.json, transients via Site Health → Info, plugins/themes JSON exports. | External APIs you're calling — you'd open the response in a separate tab anyway. |
| Browser extension | Inspecting REST API responses (yours or anyone's), production payloads, third-party JSON, JSONP responses, configs hosted on GitHub Raw. | Anything inside wp-admin where you'd rather not leave the page. |
| npm CLI | Build-time validation (CI step on theme.json + block.json), batch transformations (CSV → JSON, YAML → JSON, etc.), scripted diffs. | One-off debugging when you're already in a browser. |
You don't need all three. The free WP plugin alone covers most WP-internal debugging. The free browser extension alone covers most REST API debugging. Pick what fits your day.
What jsonyo does NOT do
- No JSON Schema validation. If you have a JSON Schema and want to validate a payload against it, use
ajvfrom npm. We thought about adding it; it would balloon the engine 5x and it's not in the 80% need-band. - No JSON-to-TS / JSON-to-Go conversion in the browser surfaces. The npm CLI has it (
jsonyo gen-types), the browser surfaces don't — too easy to misuse without a CLI's flag-driven control. - No filter expressions in JSONPath (
[?(@.x>1)]). Use the CLI's--jsmode for that. - No save / load workspaces. Each session is ephemeral. We thought about persisting last input — privacy-by-default won.
- No cloud sync, no account, no telemetry. Plugin is GPLv2, extension is MV3 with zero permissions. The External Services disclosure on the WP plugin's readme is one word: NONE.
Privacy & data handling
The whole point of the tool is that none of your JSON leaves the page:
- WP plugin: No outbound API calls. Ever.
External Servicesdisclosure: NONE. No database options stored. No usermeta. No site-wide transients. - Browser extension: Manifest V3 with
permissions: []andhost_permissions: []. No content scripts. No analytics. The popup runs locally in browser memory. - npm CLI: Read stdin, write stdout. Doesn't even touch
~/.config.
One engine across three surfaces
This is the part most JSON tools don't bother with: byte-identical output across CLI, browser, and WP plugin. Same 350-line vanilla JS engine in all three. If jsonyo query "$..acf" returns 47 matches in your terminal, the browser extension on the same payload returns 47 matches, and the WP plugin returns 47 matches. No "well, the CLI version uses minimatch but the browser uses regex" surprises.
Practical benefit: you can reproduce a CLI bug inside the browser by just pasting the input. You can prototype a query in the browser before scripting it through the CLI. You can verify a WP plugin's output by running the same payload through the CLI in CI.
jsonyo — pick a surface, all free, all share the same engine
WP plugin and browser extension are both v1.0.0 code-complete, queued for store reviews. The npm CLI is already production at v2.0.2.