Add Dumas JSON object iterator node

This commit is contained in:
2026-07-21 10:52:48 +00:00
parent 6994cb64c5
commit 5446a5c068
3 changed files with 75 additions and 0 deletions

View File

@@ -44,6 +44,11 @@
- Outputs: `item`, `current_index`, `total_items` - Outputs: `item`, `current_index`, `total_items`
- Returns the current array item and position, with `mode` set to `fixed`, `incr`, or `decr`. - Returns the current array item and position, with `mode` set to `fixed`, `incr`, or `decr`.
- `Dumas JSON Object Iterator`
- Inputs: `json_input`, `index`, `mode`
- Outputs: `key`, `value`, `current_index`, `total_items`
- Returns the current object entry in insertion order, with `mode` set to `fixed`, `incr`, or `decr`.
All nodes live in the `Dumas/JSON` category. All nodes live in the `Dumas/JSON` category.
## Installation ## Installation
@@ -90,6 +95,8 @@ incr -> use index + 1
decr -> use index - 1 decr -> use index - 1
``` ```
`Dumas JSON Object Iterator` uses the same index rules and iterates object entries in their existing key order.
## Roadmap ## Roadmap
This repo is intended to grow into a broader set of Dumas-branded generic utility nodes, including JSON helpers and adjacent data-manipulation tools. This repo is intended to grow into a broader set of Dumas-branded generic utility nodes, including JSON helpers and adjacent data-manipulation tools.

View File

@@ -270,6 +270,36 @@ class DumasJSONArrayIteratorNode:
return (json_input[current_index], current_index, total_items) return (json_input[current_index], current_index, total_items)
class DumasJSONObjectIteratorNode:
CATEGORY = "Dumas/JSON"
RETURN_TYPES = ("STRING", "JSON", "INT", "INT")
RETURN_NAMES = ("key", "value", "current_index", "total_items")
FUNCTION = "iterate"
@classmethod
def INPUT_TYPES(cls):
return {
"required": {
"json_input": ("JSON",),
"index": ("INT", {"default": 0, "min": 0, "step": 1}),
"mode": (["fixed", "incr", "decr"], {"default": "fixed"}),
}
}
def iterate(self, json_input, index, mode):
if not isinstance(json_input, dict):
return (None, None, -1, 0)
items = list(json_input.items())
total_items = len(items)
if total_items == 0:
return (None, None, -1, 0)
current_index = _resolve_iteration_index(index, mode, total_items)
key, value = items[current_index]
return (key, value, current_index, total_items)
NODE_CLASS_MAPPINGS = { NODE_CLASS_MAPPINGS = {
"DumasJSONStringToObject": DumasJSONStringToObjectNode, "DumasJSONStringToObject": DumasJSONStringToObjectNode,
"DumasJSONObjectToString": DumasJSONObjectToStringNode, "DumasJSONObjectToString": DumasJSONObjectToStringNode,
@@ -279,6 +309,7 @@ NODE_CLASS_MAPPINGS = {
"DumasJSONKeys": DumasJSONKeysNode, "DumasJSONKeys": DumasJSONKeysNode,
"DumasJSONArrayLength": DumasJSONArrayLengthNode, "DumasJSONArrayLength": DumasJSONArrayLengthNode,
"DumasJSONArrayIterator": DumasJSONArrayIteratorNode, "DumasJSONArrayIterator": DumasJSONArrayIteratorNode,
"DumasJSONObjectIterator": DumasJSONObjectIteratorNode,
} }
NODE_DISPLAY_NAME_MAPPINGS = { NODE_DISPLAY_NAME_MAPPINGS = {
@@ -290,4 +321,5 @@ NODE_DISPLAY_NAME_MAPPINGS = {
"DumasJSONKeys": "Dumas JSON Keys", "DumasJSONKeys": "Dumas JSON Keys",
"DumasJSONArrayLength": "Dumas JSON Array Length", "DumasJSONArrayLength": "Dumas JSON Array Length",
"DumasJSONArrayIterator": "Dumas JSON Array Iterator", "DumasJSONArrayIterator": "Dumas JSON Array Iterator",
"DumasJSONObjectIterator": "Dumas JSON Object Iterator",
} }

View File

@@ -6,6 +6,7 @@ from dumas_json_nodes import (
DumasJSONGetValueNode, DumasJSONGetValueNode,
DumasJSONKeysNode, DumasJSONKeysNode,
DumasJSONMergeObjectsNode, DumasJSONMergeObjectsNode,
DumasJSONObjectIteratorNode,
DumasJSONObjectToStringNode, DumasJSONObjectToStringNode,
DumasJSONStringToObjectNode, DumasJSONStringToObjectNode,
DumasJSONSetValueNode, DumasJSONSetValueNode,
@@ -109,6 +110,41 @@ class DumasJSONNodeTests(unittest.TestCase):
self.assertEqual(result, (None, -1, 0)) self.assertEqual(result, (None, -1, 0))
def test_object_iterator_fixed_mode_uses_given_index(self):
node = DumasJSONObjectIteratorNode()
result = node.iterate({"first": "a", "second": "b", "third": "c"}, 1, "fixed")
self.assertEqual(result, ("second", "b", 1, 3))
def test_object_iterator_incr_mode_advances_index(self):
node = DumasJSONObjectIteratorNode()
result = node.iterate({"first": "a", "second": "b", "third": "c"}, 1, "incr")
self.assertEqual(result, ("third", "c", 2, 3))
def test_object_iterator_decr_mode_decrements_index(self):
node = DumasJSONObjectIteratorNode()
result = node.iterate({"first": "a", "second": "b", "third": "c"}, 1, "decr")
self.assertEqual(result, ("first", "a", 0, 3))
def test_object_iterator_clamps_out_of_range_index(self):
node = DumasJSONObjectIteratorNode()
result = node.iterate({"first": "a", "second": "b", "third": "c"}, 99, "fixed")
self.assertEqual(result, ("third", "c", 2, 3))
def test_object_iterator_handles_empty_objects(self):
node = DumasJSONObjectIteratorNode()
result = node.iterate({}, 0, "fixed")
self.assertEqual(result, (None, None, -1, 0))
if __name__ == "__main__": if __name__ == "__main__":
unittest.main() unittest.main()