JSON Parser (FeiMao-326)
Turn an LLM's JSON blob into individual wires — the node that makes 'prompt from model' workflows sane
- output_1
- output_2
- output_3
- output_4
- output_5
- output_6
- output_7
- output_8
- output_9
- output_10
- output_11
- output_12
- output_13
- output_14
- output_15
- output_16
- output_17
- output_18
- output_19
- output_20
- output_21
- output_22
- output_23
- output_24
- output_25
- output_26
- output_27
- output_28
- output_29
- output_30
- output_31
- output_32
- output_33
- output_34
- output_35
- output_36
- output_37
- output_38
- output_39
- output_40
- output_41
- output_42
- output_43
- output_44
- output_45
- output_46
- output_47
- output_48
- output_49
- output_50
The annoying thing about asking an LLM for structured output is that you get a JSON blob, and ComfyUI doesn't care about JSON blobs - it cares about wires. You want the subject on one wire, the style on another, the scene on a third. That's exactly what this node is for: it takes a JSON payload, digs through it, and routes each key you ask for to its own output.
How it works
Give it json_payload (any JSON string) and keys_to_extract (a comma-separated list, like shot, subject, scene, audio), and it does a recursive search through the whole structure. The search is deep - it doesn't just look at the top level. If your payload nests subject three layers down inside some array, it still finds it. Every value it finds under a key gets joined with ", ", so a key containing an object or a list becomes a tidy comma-separated string.
That depth-first behavior is the thing to love about it. LLM output formats drift run to run; a parser that demands an exact schema breaks the moment the model reorders a key. This one shrugs and finds the data anyway.
The node exposes up to 50 outputs (output_1 through output_50), but you don't have to deal with all of them - a bundled JS extension shows and hides outputs based on which ones you actually wire up. So the practical view is "one output per key you asked for."
Wiring it into a real workflow
This node was clearly designed to sit right after an LLM call, and the pack's own recommended pipeline is:
General API Node (force_json_format ✅) → Markdown Extractor → JSON Parser
With force_json_format on, the API returns clean JSON, Markdown Extractor strips any residual code fences, and then you parse. The default payload in the node is a nice demo of the intended use: a shot list for a video, with shot, subject, scene, and audio each holding their own little nested dict. Wire output_1 (shot) into a prompt-template's subject slot, output_2 into the style slot, and you've got a workflow where the LLM literally writes your prompts piece by piece.
Inputs and outputs
Only two inputs, both strings: json_payload and keys_to_extract. That's it. No tuning, no regex, no schema definition - which is either refreshing or limited depending on your mood. If your key has a space in it or you need nested paths like metadata.camera, you're out of luck; it matches plain key names.
The outputs are output_1 … output_50, each a STRING. Keys you ask for but don't find produce empty strings rather than errors, which is graceful but means you should sanity-check a wire that comes back empty - it might be a missing key, not a blank value.
Gotchas
Invalid JSON doesn't crash your workflow. It returns ERROR: Invalid JSON format. ... in output_1 and empty strings everywhere else, so an LLM that decides to be creative with braces will show up as a very visible error string rather than a silent failure. Wire that first output into a Show Text node and you'll see it instantly.
Installing
Same pack as the rest: it's FeiMao_326_JsonParser in the FeiMao-326 category. ComfyUI Manager (search "Comfyui-General-API-Node") or:
cd ComfyUI/custom_nodes
git clone https://github.com/FeiMao-326/Comfyui-General-API-Node.git
cd Comfyui-General-API-Node
pip install -r requirements.txt
Then restart ComfyUI. Dependencies are just openai, numpy, Pillow, requests - nothing heavy, no models to download.
Inputs (2)
| Name | Type | Default | Description |
|---|---|---|---|
| json_payload | STRING | { "shot": { "composition": "central low-angle wide" }, "subject": { "description": "CBR 150 assembling" }, "scene": { "location": "desert basin" }, "audio": { "music": "trailer score" } } | — |
| keys_to_extract | STRING | shot, subject, scene, audio | — |
Outputs (50)
| Name | Type | Description |
|---|---|---|
| output_1 | STRING | — |
| output_2 | STRING | — |
| output_3 | STRING | — |
| output_4 | STRING | — |
| output_5 | STRING | — |
| output_6 | STRING | — |
| output_7 | STRING | — |
| output_8 | STRING | — |
| output_9 | STRING | — |
| output_10 | STRING | — |
| output_11 | STRING | — |
| output_12 | STRING | — |
| output_13 | STRING | — |
| output_14 | STRING | — |
| output_15 | STRING | — |
| output_16 | STRING | — |
| output_17 | STRING | — |
| output_18 | STRING | — |
| output_19 | STRING | — |
| output_20 | STRING | — |
| output_21 | STRING | — |
| output_22 | STRING | — |
| output_23 | STRING | — |
| output_24 | STRING | — |
| output_25 | STRING | — |
| output_26 | STRING | — |
| output_27 | STRING | — |
| output_28 | STRING | — |
| output_29 | STRING | — |
| output_30 | STRING | — |
| output_31 | STRING | — |
| output_32 | STRING | — |
| output_33 | STRING | — |
| output_34 | STRING | — |
| output_35 | STRING | — |
| output_36 | STRING | — |
| output_37 | STRING | — |
| output_38 | STRING | — |
| output_39 | STRING | — |
| output_40 | STRING | — |
| output_41 | STRING | — |
| output_42 | STRING | — |
| output_43 | STRING | — |
| output_44 | STRING | — |
| output_45 | STRING | — |
| output_46 | STRING | — |
| output_47 | STRING | — |
| output_48 | STRING | — |
| output_49 | STRING | — |
| output_50 | STRING | — |