Notes › Tech Notes › Long JSON where you cannot find a field: tree view, folding and search

Long JSON where you cannot find a field: tree view, folding and search

Last week I was checking an API response. The body was almost fifty thousand characters, all pressed into one line. The field I wanted was "shop_name". I typed it into the editor's find box, the cursor jumped to somewhere around character 30,000, but I could not see which object it sat in, which record it belonged to, or even whether the hit was the key or a value that happened to share the name. After that I made a rule for myself: before searching JSON, turn it into structure.

Formatting only spreads it out, it does not tell you where something is

Splitting one line into indented lines is where most people start, and it does help: readability improves immediately. But it gives you no sense of hierarchy. Counting spaces across twelve levels of indentation is slow, and once expanded, one line becomes thousands, so scrolling gets slower rather than faster.

What I do now is drop the data into JSON Viewer. Every object and array becomes a node you can collapse or expand, and there are expand-all and collapse-all controls. Finding a field stops being a question of how many lines of text you scan and becomes a question of which branches you search.

Type colour is the second signal I rely on most. Strings, numbers, booleans and null each get their own colour, so one glance tells you that "total": 20 is a number while "total": "20" is a string. In an API response they look identical and behave completely differently when something goes wrong. I once lost a long joint debugging session to "status": null versus "status": "", and since then I read the colour before the value.

Path notation: levels, keys and array indexes

A nested structure needs names before you can talk about it. My convention is dots for object levels and bracket indexes for arrays, with indexes starting at 0. That way the location of a field becomes one complete path, and saying it to a colleague, pasting it into code or writing it into a ticket all use the same string.

A concrete example:

{
  "code": 0,
  "data": {
    "list": [
      { "id": 101, "items": [ { "sku": "A-1", "name": "cup" }, { "sku": "A-2", "name": "pot" }, { "sku": "A-3", "name": "plate" } ] },
      { "id": 102, "items": [ { "sku": "B-1", "name": "pan" } ] }
    ],
    "page": { "no": 1, "size": 20, "has_more": false }
  }
}
Path notation Points to Common trap
data.page.size The number 20 When keys repeat, only one path is correct
data.list[0].items[2].name The string "plate" Indexes count from 0, so the third item is [2]
data.list[1].items[0].sku The string "B-1" An array with one item can still be mistaken for an object
data.list[0].items The whole array, 3 items A collapsed node looks empty but still holds content

Clicking any node in the tree copies its path, which saves me a lot of manual retyping. The classic mistake when copying by hand is an index off by one: you test against the wrong object and conclude the API did not return the field.

Folding, search and copying a path: when I use each

Search matches keywords against both keys and values, highlights the hits, and lets you jump to the previous or next one. I use it to answer how many times a field appears, for example when hunting duplicate keys.

I fold for two reasons. One is exclusion: once I know a branch has nothing to do with my question, I collapse it and the visible area shrinks at once. The other is compressing context: if I care about data.page, I collapse both elements of data.list and the screen is down to a few lines.

Copying a path is for output. Once I have located a field, I need it as an access expression in code, as an explanation for the backend, and as the assertion target in a test. The path string is the shared language between all three.

Pretty-printing or minifying plain text is a different job. When I need to paste JSON back into code or shrink it, I use JSON Formatter. The tree view is for reading, formatting is for writing, and I no longer use formatting as a substitute for locating.

There is also a need the search box cannot meet: finding every key that ends in _url. Keyword search is no help there, so I hand the content to Regex Tester, pull the candidate lines out of the plain text first, then go back to the tree to confirm the level.

Q: Why does searching for "name" land somewhere other than the field I want?

Because "name" appears many times in a nested structure, and the hit order is just the order of positions in the text. Check how many hits there are, step through them with previous and next, and fold unrelated branches out of the way.

Q: Do I need both the tree view and the formatter?

Use the view to read data and the formatter to change it. The view gives you structure and paths; the formatter gives you pasteable text. They point in opposite directions, and substituting one for the other is awkward.

Q: Can I look at only the first few items of a very long array?

What I do is collapse the elements I do not need and expand only the indexes I care about. Expanding a thousand elements one by one achieves nothing; problems usually sit at a few specific indexes.

Q: The API JSON contains Chinese text and escape characters. Will the view mislead me?

Escape sequences in values, such as \n and \", are shown as the characters themselves in the tree, so read them as the original characters. Actually handling escapes is a job for the code.

Q: The data is sensitive, so I do not want to paste it into an online tool.

My test is whether the tool sends the content anywhere. If it processes everything in the browser and the data never leaves the machine, I will paste even a sensitive response body. If the only option requires an upload, I go back to a local editor with a plugin.

That "shop_name" took me half an hour to find. The answer was that it sat under data.list[1].items[0], while the record I wanted was in element 0. Both had a field with the same name, and the first one I hit was the wrong one. Since then I count the hits first and then decide which branch to expand, which is the reverse of my old order. That is probably the most practical fix for this kind of problem.

📎 Related articles

PNG compressed three times only lost 426 bytes: the real boundary of lossless compression 2026-10-22 How Many Times Bigger a PNG Gets After Converting From WebP: When It Is Unavoidable and How to Keep the Growth Down 2026-10-22 Three Reasons the Small Text Smudges When a Screenshot Is Shrunk to a Quarter 2026-10-22 Cropped to the Same 300x300, Why Does the Avatar Always Sit Half a Cell Low-Right 2026-10-22 Forecasting 18 months at 1.7 times a month: why the script and the sheet give two numbers 2026-10-22