JB · Extractor
Pull one subtree out of a JSON prompt — for regional detailer passes and reuse
- raw_json
- string
- found
The JB suite builds one big structured document, and then most of the time you want part of it. JB · Extractor is the knife: it pulls one or more named subtrees out of a JSON string and hands them back as their own mini-document. The canonical use is regional detailing - you've stitched a whole character document, but the face-detailing pass only needs character_1.outfit.garments.upper_body, so you extract that one branch and feed it to a regional prompt rather than re-prompting by hand.
It's a small node with a four-mode personality, and the mode is auto-selected by what you type into category.
The four modes
- Single key - type
hairand it recursively searches every nesting level for the firsthairkey, returning{hair: value}. Great when you don't know exactly which level the key lives at. - Dot-path - type
character_1.outfit.garments.upper_bodyand it does a strict descent down that exact path, returning{upper_body: value}. Precise, and fails cleanly if the path doesn't exist. - Multi - separate categories with commas/newlines/semicolons, e.g.
hair, eyes, shoes. Each is resolved independently and the results merge into one{key: value}dict. Missing categories are skipped silently. - Empty - leave
categoryblank and you get the whole input back unwrapped. Handy as a passthrough/debug switch.
The output_format choice (pretty_json, compact_json, loose_keys) applies to whatever comes out. And there's a found boolean output - true if at least one category matched - which you can wire into a condition to branch your workflow instead of relying on string inspection.
What it's actually for
Think of it as the re-use and plumbing node of the JB suite. The Stitcher produces one giant document per character; the Extractor lets you slice that document into focused prompts for different stages - a full-body prompt for the base pass, a hair+face subset for a face detailer, the shoes alone for a footwear ControlNet pass. Because it takes a plain STRING input, it doesn't care whether the JSON came from a Stitcher, a Builder, an Ideogram Assembler, or a text file you typed yourself.
Installing
cd ComfyUI/custom_nodes
git clone https://github.com/ping1979ping/comfyui-FVMtools
No dependencies, pure string parsing, instant. Restart ComfyUI and it's under FVM Tools/JB.
The gotchas
Two, both about silent behavior. Single-key search returns the first match in document order - if hair appears for both character_1 and character_2 and you search single-key, you get whichever comes first, with no warning. Use the dot-path mode when key names repeat. And multi-mode skips missing categories silently: if you ask for eyes, nonexistent_field, you get {eyes: ...} with no error telling you the second one wasn't found - check the found output or the returned document before assuming you got everything.
Inputs (5)
| Name | Type | Default | Description |
|---|---|---|---|
| json_input | STRING | JSON to search. Wire a raw_json output here — the loose_keys `string` output is one-way and cannot be parsed back. | |
| category | STRING | What to pull out. Four syntaxes, auto-detected: face → single key, recursive search through every nesting level. Wraps as {face: ...}. face, hair → several keys at once. Separators: comma, semicolon, or one per line. Keys that aren't found are skipped silently. character_1.face → dot-path, strict descent from the root. Wraps under the LAST segment: {face: ...}. (empty) → the whole document, unwrapped. Dots are path separators, never list separators — 'a.b, c.d' is two paths. With collect_all ON the meaning of a dot-path changes: all but the last segment is a strict descent that SCOPES the search, and the last segment is then collected recursively below it. So 'input_4.prompt_fragment' sweeps every prompt_fragment inside input_4 only. Careful: two dot-paths ending in the same segment share one wrap key. Their values merge (collect_all: appended; otherwise: last one wins). Prefix a line with [NOT] to EXCLUDE instead of pull: [NOT]key → drop that key + subtree everywhere [NOT]a.b.c → drop just that path Exclusions are pruned from the source first. [NOT] lines alone → the whole document minus those keys. If they empty the result → found=False. | |
| output_format | COMBO | loose_keys | pretty_json / compact_json → strict JSON. loose_keys → unquoted keys for SD/CLIP encoders; with collect_all it collapses to one flat comma-joined line. |
| collect_all | BOOLEAN | false | OFF: return the FIRST match of a key. ON: collect EVERY match at any depth into a list — the classic 'give me all prompt_fragments' case. A dot-path then SCOPES the sweep instead of pinpointing one value: all but the last segment is a strict descent, the last segment is searched recursively below it. With output_format=loose_keys the string output becomes one flat comma-joined line. |
| with_keys | BOOLEAN | false | Only applies when collect_all is ON. OFF: bare values — 'wallpapered feature wall, shag area rug'. ON: each value keeps the key of the element it came from — 'background: wallpapered feature wall, midground: shag area rug'. raw_json becomes {key: {background: ..., midground: ...}} instead of a flat list. Repeated element names collect into a list rather than overwriting. |
Outputs (3)
| Name | Type | Description |
|---|---|---|
| raw_json | STRING | — |
| string | STRING | — |
| found | BOOLEAN | — |