add create DICT and LIST from JSON string

This commit is contained in:
StableLlama
2026-09-09 10:29:14 +02:00
parent eac17833e1
commit b46f4ba2bf
6 changed files with 117 additions and 2 deletions
+5
View File
@@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [Unreleased]
- Add "create DICT from JSON string" and "create LIST from JSON string" nodes to
parse a multiline JSON object/array into a DICT/LIST
## [1.8.1] - 2026-09-06
- Add optional additional input for image saving to also save the prompt when provided
+2 -2
View File
@@ -71,7 +71,7 @@ ComfyUI list manipulation nodes (for processing individual items):
Dictionary manipulation nodes:
- **Creation**: create (generic and type-specific), create from items, create from lists, fromkeys
- **Creation**: create (generic and type-specific), create from JSON string, create from items, create from lists, fromkeys
- **Access**: get, get_multiple, keys, values, items
- **Modification**: set, update, setdefault, merge
- **Removal**: pop, popitem, pop random, remove
@@ -102,7 +102,7 @@ Integer operation nodes:
Python list manipulation nodes (as a single variable):
- **Creation**: create LIST (generic and type-specific versions)
- **Creation**: create LIST (generic and type-specific versions), create LIST from JSON string
- **Modification**: append, extend, insert, remove, pop, pop random, set_item, shuffle
- **Access**: get_item, first, last, slice, index, contains
- **Information**: length, count
+39
View File
@@ -4,6 +4,7 @@ from typing import (
)
from inspect import cleandoc
import json
import random
try:
@@ -1067,12 +1068,49 @@ class DictValues(ComfyNodeABC):
return (list(input_dict.values()),)
class DictCreateFromJSONString(ComfyNodeABC):
"""
Creates a DICT from a JSON object string.
This node takes a STRING that must contain a valid JSON object and
parses it into a DICT. The input must be a JSON object (enclosed in curly
braces); otherwise a clear error is raised.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"json_string": (IO.STRING, {"default": "{}", "widgetType": "STRING", "tooltip": "STRING containing a JSON object to parse, e.g. {\"a\": 1}."}),
}
}
RETURN_TYPES = ("DICT",)
RETURN_NAMES = ("dict",)
OUTPUT_TOOLTIPS = ("The DICT parsed from the JSON object string.",)
CATEGORY = "Basic/DICT"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "create_from_json"
def create_from_json(self, json_string: str) -> tuple[dict]:
try:
result = json.loads(json_string)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON in input string: {e}")
if not isinstance(result, dict):
raise ValueError(
"The JSON string must be a JSON object (enclosed in curly braces), "
f"not {type(result).__name__}."
)
return (result,)
NODE_CLASS_MAPPINGS = {
"Basic data handling: DictCreate": DictCreate,
"Basic data handling: DictCreateFromBoolean": DictCreateFromBoolean,
"Basic data handling: DictCreateFromFloat": DictCreateFromFloat,
"Basic data handling: DictCreateFromInt": DictCreateFromInt,
"Basic data handling: DictCreateFromString": DictCreateFromString,
"Basic data handling: DictCreateFromJSONString": DictCreateFromJSONString,
"Basic data handling: DictCreateFromItemsDataList": DictCreateFromItemsDataList,
"Basic data handling: DictCreateFromItemsList": DictCreateFromItemsList,
"Basic data handling: DictCreateFromLists": DictCreateFromLists,
@@ -1105,6 +1143,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: DictCreateFromFloat": "create DICT from FLOATs",
"Basic data handling: DictCreateFromInt": "create DICT from INTs",
"Basic data handling: DictCreateFromString": "create DICT from STRINGs",
"Basic data handling: DictCreateFromJSONString": "create DICT from JSON string",
"Basic data handling: DictCreateFromItemsDataList": "create from items (data list)",
"Basic data handling: DictCreateFromItemsList": "create from items (LIST)",
"Basic data handling: DictCreateFromLists": "create from LISTs",
+39
View File
@@ -1,5 +1,6 @@
from typing import Any
from inspect import cleandoc
import json
try:
from comfy.comfy_types.node_typing import IO, ComfyNodeABC
@@ -972,12 +973,49 @@ class ListToSet(ComfyNodeABC):
return (set(list),)
class ListCreateFromJSONString(ComfyNodeABC):
"""
Creates a LIST from a JSON array string.
This node takes a STRING that must contain a valid JSON array and
parses it into a LIST. The input must be a JSON array (enclosed in square
brackets); otherwise a clear error is raised.
"""
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"json_string": (IO.STRING, {"default": "[]", "widgetType": "STRING", "tooltip": "STRING containing a JSON array to parse, e.g. [1, 2, 3]."}),
}
}
RETURN_TYPES = ("LIST",)
RETURN_NAMES = ("list",)
OUTPUT_TOOLTIPS = ("The LIST parsed from the JSON array string.",)
CATEGORY = "Basic/LIST"
DESCRIPTION = cleandoc(__doc__ or "")
FUNCTION = "create_from_json"
def create_from_json(self, json_string: str) -> tuple[list[Any]]:
try:
result = json.loads(json_string)
except json.JSONDecodeError as e:
raise ValueError(f"Invalid JSON in input string: {e}")
if not isinstance(result, list):
raise ValueError(
"The JSON string must be a JSON array (enclosed in square brackets), "
f"not {type(result).__name__}."
)
return (result,)
NODE_CLASS_MAPPINGS = {
"Basic data handling: ListCreate": ListCreate,
"Basic data handling: ListCreateFromBoolean": ListCreateFromBoolean,
"Basic data handling: ListCreateFromFloat": ListCreateFromFloat,
"Basic data handling: ListCreateFromInt": ListCreateFromInt,
"Basic data handling: ListCreateFromString": ListCreateFromString,
"Basic data handling: ListCreateFromJSONString": ListCreateFromJSONString,
"Basic data handling: ListAll": ListAll,
"Basic data handling: ListAny": ListAny,
"Basic data handling: ListAppend": ListAppend,
@@ -1013,6 +1051,7 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"Basic data handling: ListCreateFromFloat": "create LIST from FLOATs",
"Basic data handling: ListCreateFromInt": "create LIST from INTs",
"Basic data handling: ListCreateFromString": "create LIST from STRINGs",
"Basic data handling: ListCreateFromJSONString": "create LIST from JSON string",
"Basic data handling: ListAll": "all",
"Basic data handling: ListAny": "any",
"Basic data handling: ListAppend": "append",
+15
View File
@@ -11,6 +11,7 @@ from src.basic_data_handling.dict_nodes import (
DictCreateFromItemsList,
DictCreateFromLists,
DictCreateFromString,
DictCreateFromJSONString,
DictExcludeKeys,
DictFilterByKeys,
DictFromKeys,
@@ -112,6 +113,20 @@ def test_dict_create_from_string():
assert node.create() == ({},)
def test_dict_create_from_json_string():
node = DictCreateFromJSONString()
# Single-line JSON object
assert node.create_from_json('{\n "key1": "value1",\n "key2": 2\n}') == ({"key1": "value1", "key2": 2},)
# Empty object
assert node.create_from_json("{}") == ({},)
# JSON array is not a valid object -> error
with pytest.raises(ValueError, match="JSON object"):
node.create_from_json("[1, 2, 3]")
# Malformed JSON -> error
with pytest.raises(ValueError):
node.create_from_json("{not json}")
def test_dict_create_from_items_datalist():
node = DictCreateFromItemsDataList()
assert node.create_from_items(item=[("key1", "value1"), ("key2", "value2")]) == (_dict_x2,)
+17
View File
@@ -10,6 +10,7 @@ from src.basic_data_handling.list_nodes import (
ListCreateFromFloat,
ListCreateFromInt,
ListCreateFromString,
ListCreateFromJSONString,
ListEnumerate,
ListExtend,
ListFirst,
@@ -257,6 +258,22 @@ def test_list_create_from_string():
assert node.create_list() == ([],)
def test_list_create_from_json_string():
node = ListCreateFromJSONString()
# Multiline JSON array
assert node.create_from_json('[\n 1,\n 2,\n 3\n]') == ([1, 2, 3],)
# Empty array
assert node.create_from_json("[]") == ([],)
# Mix of JSON types
assert node.create_from_json('["a", 1, true, null]') == (["a", 1, True, None],)
# JSON object is not a valid array -> error
with pytest.raises(ValueError, match="JSON array"):
node.create_from_json('{"a": 1}')
# Malformed JSON -> error
with pytest.raises(ValueError):
node.create_from_json("[1, 2,")
def test_list_to_data_list():
node = ListToDataList()
input_list = [1, 2, 3]