Files
qbug 621b889e38 feat(nodes): introduce comprehensive JSON management nodes
- Added new nodes for JSON manipulation: RandomJSONValueNode, JSONObjectIteratorNode, JSONArrayIteratorNode, JSONMergeNode, JSONModifierNode, JSONGeneratorNode, JSONLengthNode, JSONKeyCheckerNode, and JSONStringifierNode.
- Updated __init__.py to include new node classes and their display names.
- Enhanced README documentation to reflect new features and usage examples.
- Bumped version to 1.1.0 in pyproject.toml to signify the addition of new functionalities.

This update significantly expands the capabilities of the JSON handling nodes in ComfyUI, providing users with a robust toolkit for JSON data processing.
2024-12-25 22:33:25 +08:00

133 lines
4.4 KiB
Python

import json
from typing import Union, Tuple
import time
class JSONObjectIteratorNode:
stored_index = 0
last_update_time = 0
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"json_input": ("STRING", {"multiline": True}),
"index": ("INT", {"default": 0, "min": 0}),
"mode": (["fixed", "incr", "decr"], {"default": "fixed"}),
},
}
RETURN_TYPES = ("STRING", "STRING", "INT", "INT")
RETURN_NAMES = ("key", "value", "current_index", "total_items")
FUNCTION = "iterate_object"
CATEGORY = "utils"
@classmethod
def IS_CHANGED(cls, **kwargs) -> float:
mode = kwargs.get("mode", "fixed")
if mode != "fixed":
# 返回当前时间戳,确保节点会在每次执行时重新运行
return time.time()
return float("NaN")
def iterate_object(self, json_input: str, index: int, mode: str) -> Tuple[str, str, int, int]:
try:
data = json.loads(json_input)
if not isinstance(data, dict):
raise ValueError("Input must be a JSON object")
items = list(data.items())
total_items = len(items)
if total_items == 0:
return ("", "", 0, 0)
# 使用存储的索引或初始索引
current_index = self.stored_index if mode != "fixed" else index
current_index = current_index % total_items
# 根据模式计算下一个索引
if mode == "incr":
next_index = (current_index + 1) % total_items
elif mode == "decr":
next_index = (current_index - 1) % total_items
else: # fixed
next_index = current_index
# 更新存储的索引
if mode != "fixed":
self.__class__.stored_index = next_index
key, value = items[current_index]
if isinstance(value, (dict, list)):
value = json.dumps(value)
else:
value = str(value)
return (str(key), value, current_index, total_items)
except json.JSONDecodeError:
raise ValueError("Invalid JSON input")
class JSONArrayIteratorNode:
stored_index = 0
last_update_time = 0
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"json_input": ("STRING", {"multiline": True}),
"index": ("INT", {"default": 0, "min": 0}),
"mode": (["fixed", "incr", "decr"], {"default": "fixed"}),
},
}
RETURN_TYPES = ("STRING", "INT", "INT")
RETURN_NAMES = ("item", "current_index", "total_items")
FUNCTION = "iterate_array"
CATEGORY = "utils"
@classmethod
def IS_CHANGED(cls, **kwargs) -> float:
mode = kwargs.get("mode", "fixed")
if mode != "fixed":
# 返回当前时间戳,确保节点会在每次执行时重新运行
return time.time()
return float("NaN")
def iterate_array(self, json_input: str, index: int, mode: str) -> Tuple[str, int, int]:
try:
data = json.loads(json_input)
if not isinstance(data, list):
raise ValueError("Input must be a JSON array")
total_items = len(data)
if total_items == 0:
return ("", 0, 0)
# 使用存储的索引或初始索引
current_index = self.stored_index if mode != "fixed" else index
current_index = current_index % total_items
# 根据模式计算下一个索引
if mode == "incr":
next_index = (current_index + 1) % total_items
elif mode == "decr":
next_index = (current_index - 1) % total_items
else: # fixed
next_index = current_index
# 更新存储的索引
if mode != "fixed":
self.__class__.stored_index = next_index
item = data[current_index]
if isinstance(item, (dict, list)):
item = json.dumps(item)
else:
item = str(item)
return (item, current_index, total_items)
except json.JSONDecodeError:
raise ValueError("Invalid JSON input")