Add Dumas JSON utility batch
This commit is contained in:
47
README.md
47
README.md
@@ -24,6 +24,21 @@
|
|||||||
- Output: updated `JSON`
|
- Output: updated `JSON`
|
||||||
- Writes a parsed JSON value into a nested path without mutating the original object.
|
- Writes a parsed JSON value into a nested path without mutating the original object.
|
||||||
|
|
||||||
|
- `Dumas JSON Has Key`
|
||||||
|
- Inputs: `json_object`, `path`
|
||||||
|
- Output: `BOOLEAN`
|
||||||
|
- Checks whether a nested path exists.
|
||||||
|
|
||||||
|
- `Dumas JSON Remove Key`
|
||||||
|
- Inputs: `json_object`, `path`
|
||||||
|
- Output: updated `JSON`
|
||||||
|
- Removes a nested key or array item by path.
|
||||||
|
|
||||||
|
- `Dumas JSON Pick Fields`
|
||||||
|
- Inputs: `json_object`, `paths`
|
||||||
|
- Output: filtered `JSON`
|
||||||
|
- Builds a new object from newline-separated paths that exist in the input.
|
||||||
|
|
||||||
- `Dumas JSON Merge Objects`
|
- `Dumas JSON Merge Objects`
|
||||||
- Inputs: `base_object`, `overlay_object`
|
- Inputs: `base_object`, `overlay_object`
|
||||||
- Output: merged `JSON`
|
- Output: merged `JSON`
|
||||||
@@ -39,6 +54,16 @@
|
|||||||
- Output: `INT`
|
- Output: `INT`
|
||||||
- Returns the length of a JSON array.
|
- Returns the length of a JSON array.
|
||||||
|
|
||||||
|
- `Dumas JSON Array Append`
|
||||||
|
- Inputs: `json_array`, `value_json`
|
||||||
|
- Output: updated `JSON`
|
||||||
|
- Appends a parsed JSON value to the end of an array.
|
||||||
|
|
||||||
|
- `Dumas JSON Array Slice`
|
||||||
|
- Inputs: `json_array`, `start`, `end`, `step`
|
||||||
|
- Output: sliced `JSON`
|
||||||
|
- Returns an array slice. `end=0` means "slice to the end".
|
||||||
|
|
||||||
- `Dumas JSON Array Iterator`
|
- `Dumas JSON Array Iterator`
|
||||||
- Inputs: `json_input`, `index`, `mode`
|
- Inputs: `json_input`, `index`, `mode`
|
||||||
- Outputs: `item`, `current_index`, `total_items`
|
- Outputs: `item`, `current_index`, `total_items`
|
||||||
@@ -49,6 +74,16 @@
|
|||||||
- Outputs: `key`, `value`, `current_index`, `total_items`
|
- Outputs: `key`, `value`, `current_index`, `total_items`
|
||||||
- Returns the current object entry in insertion order, with `mode` set to `fixed`, `incr`, or `decr`.
|
- Returns the current object entry in insertion order, with `mode` set to `fixed`, `incr`, or `decr`.
|
||||||
|
|
||||||
|
- `Dumas JSON Flatten`
|
||||||
|
- Input: `json_input`
|
||||||
|
- Output: flat `JSON`
|
||||||
|
- Flattens nested objects and arrays into dot-path keys.
|
||||||
|
|
||||||
|
- `Dumas JSON Unflatten`
|
||||||
|
- Input: `flat_json_object`
|
||||||
|
- Output: nested `JSON`
|
||||||
|
- Rebuilds nested JSON from a flat dot-path object.
|
||||||
|
|
||||||
All nodes live in the `Dumas/JSON` category.
|
All nodes live in the `Dumas/JSON` category.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
@@ -87,6 +122,16 @@ settings.render.width
|
|||||||
{"enabled": true, "retries": 3}
|
{"enabled": true, "retries": 3}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
`Dumas JSON Pick Fields` expects one path per line:
|
||||||
|
|
||||||
|
```text
|
||||||
|
user.name
|
||||||
|
meta.active
|
||||||
|
items.0.id
|
||||||
|
```
|
||||||
|
|
||||||
|
`Dumas JSON Array Slice` treats `end=0` as "use the rest of the array".
|
||||||
|
|
||||||
`Dumas JSON Array Iterator` clamps to valid bounds:
|
`Dumas JSON Array Iterator` clamps to valid bounds:
|
||||||
|
|
||||||
```text
|
```text
|
||||||
@@ -97,6 +142,8 @@ decr -> use index - 1
|
|||||||
|
|
||||||
`Dumas JSON Object Iterator` uses the same index rules and iterates object entries in their existing key order.
|
`Dumas JSON Object Iterator` uses the same index rules and iterates object entries in their existing key order.
|
||||||
|
|
||||||
|
`Dumas JSON Flatten` and `Dumas JSON Unflatten` use the same dot-path format as the other path-based nodes.
|
||||||
|
|
||||||
## 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.
|
||||||
|
|||||||
@@ -43,6 +43,21 @@ def _get_json_path_value(data, path):
|
|||||||
return current
|
return current
|
||||||
|
|
||||||
|
|
||||||
|
def _has_json_path(data, path):
|
||||||
|
current = data
|
||||||
|
for segment in _parse_json_path(path):
|
||||||
|
if isinstance(segment, int):
|
||||||
|
if not isinstance(current, list) or segment >= len(current):
|
||||||
|
return False
|
||||||
|
current = current[segment]
|
||||||
|
continue
|
||||||
|
|
||||||
|
if not isinstance(current, dict) or segment not in current:
|
||||||
|
return False
|
||||||
|
current = current[segment]
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _build_missing_container(next_segment):
|
def _build_missing_container(next_segment):
|
||||||
return [] if isinstance(next_segment, int) else {}
|
return [] if isinstance(next_segment, int) else {}
|
||||||
|
|
||||||
@@ -104,6 +119,50 @@ def _set_json_path_value(data, path, value):
|
|||||||
return _set_json_path_value_recursive(data, segments, value)
|
return _set_json_path_value_recursive(data, segments, value)
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_json_path_value_recursive(current, segments):
|
||||||
|
if not segments:
|
||||||
|
return _clone_container(current)
|
||||||
|
|
||||||
|
segment = segments[0]
|
||||||
|
is_last = len(segments) == 1
|
||||||
|
|
||||||
|
if isinstance(segment, int):
|
||||||
|
if not isinstance(current, list) or segment >= len(current):
|
||||||
|
return None
|
||||||
|
|
||||||
|
result = list(current)
|
||||||
|
if is_last:
|
||||||
|
del result[segment]
|
||||||
|
return result
|
||||||
|
|
||||||
|
updated = _remove_json_path_value_recursive(result[segment], segments[1:])
|
||||||
|
if updated is None:
|
||||||
|
return None
|
||||||
|
result[segment] = updated
|
||||||
|
return result
|
||||||
|
|
||||||
|
if not isinstance(current, dict) or segment not in current:
|
||||||
|
return None
|
||||||
|
|
||||||
|
result = dict(current)
|
||||||
|
if is_last:
|
||||||
|
del result[segment]
|
||||||
|
return result
|
||||||
|
|
||||||
|
updated = _remove_json_path_value_recursive(result[segment], segments[1:])
|
||||||
|
if updated is None:
|
||||||
|
return None
|
||||||
|
result[segment] = updated
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _remove_json_path_value(data, path):
|
||||||
|
segments = _parse_json_path(path)
|
||||||
|
if not segments:
|
||||||
|
return _clone_container(data)
|
||||||
|
return _remove_json_path_value_recursive(data, segments)
|
||||||
|
|
||||||
|
|
||||||
def _merge_json_objects(base_object, overlay_object):
|
def _merge_json_objects(base_object, overlay_object):
|
||||||
if not isinstance(base_object, dict) or not isinstance(overlay_object, dict):
|
if not isinstance(base_object, dict) or not isinstance(overlay_object, dict):
|
||||||
return None
|
return None
|
||||||
@@ -118,6 +177,46 @@ def _merge_json_objects(base_object, overlay_object):
|
|||||||
return merged
|
return merged
|
||||||
|
|
||||||
|
|
||||||
|
def _flatten_json_value(value, prefix="", result=None):
|
||||||
|
if result is None:
|
||||||
|
result = {}
|
||||||
|
|
||||||
|
if isinstance(value, dict):
|
||||||
|
if not value and prefix:
|
||||||
|
result[prefix] = {}
|
||||||
|
return result
|
||||||
|
for key, nested_value in value.items():
|
||||||
|
next_prefix = f"{prefix}.{key}" if prefix else str(key)
|
||||||
|
_flatten_json_value(nested_value, next_prefix, result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
if isinstance(value, list):
|
||||||
|
if not value and prefix:
|
||||||
|
result[prefix] = []
|
||||||
|
return result
|
||||||
|
for index, nested_value in enumerate(value):
|
||||||
|
next_prefix = f"{prefix}.{index}" if prefix else str(index)
|
||||||
|
_flatten_json_value(nested_value, next_prefix, result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
result[prefix] = value
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
def _unflatten_json_object(flat_object):
|
||||||
|
if not isinstance(flat_object, dict):
|
||||||
|
return None
|
||||||
|
|
||||||
|
result = {}
|
||||||
|
for path, value in flat_object.items():
|
||||||
|
if not isinstance(path, str):
|
||||||
|
return None
|
||||||
|
result = _set_json_path_value(result, path, value)
|
||||||
|
if result is None:
|
||||||
|
return None
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
def _resolve_iteration_index(index, mode, total_items):
|
def _resolve_iteration_index(index, mode, total_items):
|
||||||
if total_items <= 0:
|
if total_items <= 0:
|
||||||
return -1
|
return -1
|
||||||
@@ -216,6 +315,69 @@ class DumasJSONSetValueNode:
|
|||||||
return (_set_json_path_value(json_object, path, value),)
|
return (_set_json_path_value(json_object, path, value),)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONHasKeyNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("BOOLEAN",)
|
||||||
|
FUNCTION = "has_key"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_object": ("JSON",),
|
||||||
|
"path": ("STRING", {"default": "", "multiline": False}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def has_key(self, json_object, path):
|
||||||
|
return (_has_json_path(json_object, path),)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONRemoveKeyNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "remove_key"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_object": ("JSON",),
|
||||||
|
"path": ("STRING", {"default": "", "multiline": False}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def remove_key(self, json_object, path):
|
||||||
|
return (_remove_json_path_value(json_object, path),)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONPickFieldsNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "pick_fields"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_object": ("JSON",),
|
||||||
|
"paths": ("STRING", {"multiline": True, "default": ""}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def pick_fields(self, json_object, paths):
|
||||||
|
result = {}
|
||||||
|
for raw_path in paths.splitlines():
|
||||||
|
path = raw_path.strip()
|
||||||
|
if not path or not _has_json_path(json_object, path):
|
||||||
|
continue
|
||||||
|
value = _get_json_path_value(json_object, path)
|
||||||
|
result = _set_json_path_value(result, path, value)
|
||||||
|
if result is None:
|
||||||
|
return (None,)
|
||||||
|
return (result,)
|
||||||
|
|
||||||
|
|
||||||
class DumasJSONMergeObjectsNode:
|
class DumasJSONMergeObjectsNode:
|
||||||
CATEGORY = "Dumas/JSON"
|
CATEGORY = "Dumas/JSON"
|
||||||
RETURN_TYPES = ("JSON",)
|
RETURN_TYPES = ("JSON",)
|
||||||
@@ -274,6 +436,56 @@ class DumasJSONArrayLengthNode:
|
|||||||
return (len(json_array),)
|
return (len(json_array),)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONArrayAppendNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "append_item"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_array": ("JSON",),
|
||||||
|
"value_json": ("STRING", {"multiline": True, "default": "null"}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def append_item(self, json_array, value_json):
|
||||||
|
if not isinstance(json_array, list):
|
||||||
|
return (None,)
|
||||||
|
try:
|
||||||
|
value = json.loads(value_json)
|
||||||
|
except json.JSONDecodeError as exc:
|
||||||
|
print(f"[DumasNodes] Error decoding JSON value: {exc}")
|
||||||
|
return (None,)
|
||||||
|
result = list(json_array)
|
||||||
|
result.append(value)
|
||||||
|
return (result,)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONArraySliceNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "slice_array"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_array": ("JSON",),
|
||||||
|
"start": ("INT", {"default": 0, "step": 1}),
|
||||||
|
"end": ("INT", {"default": 0, "step": 1}),
|
||||||
|
"step": ("INT", {"default": 1, "step": 1, "min": 1}),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def slice_array(self, json_array, start, end, step):
|
||||||
|
if not isinstance(json_array, list):
|
||||||
|
return (None,)
|
||||||
|
actual_end = None if end == 0 else end
|
||||||
|
return (json_array[start:actual_end:step],)
|
||||||
|
|
||||||
|
|
||||||
class DumasJSONArrayIteratorNode:
|
class DumasJSONArrayIteratorNode:
|
||||||
CATEGORY = "Dumas/JSON"
|
CATEGORY = "Dumas/JSON"
|
||||||
RETURN_TYPES = ("JSON", "INT", "INT")
|
RETURN_TYPES = ("JSON", "INT", "INT")
|
||||||
@@ -331,16 +543,57 @@ class DumasJSONObjectIteratorNode:
|
|||||||
return (key, value, current_index, total_items)
|
return (key, value, current_index, total_items)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONFlattenNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "flatten_json"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"json_input": ("JSON",),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def flatten_json(self, json_input):
|
||||||
|
return (_flatten_json_value(json_input),)
|
||||||
|
|
||||||
|
|
||||||
|
class DumasJSONUnflattenNode:
|
||||||
|
CATEGORY = "Dumas/JSON"
|
||||||
|
RETURN_TYPES = ("JSON",)
|
||||||
|
FUNCTION = "unflatten_json"
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def INPUT_TYPES(cls):
|
||||||
|
return {
|
||||||
|
"required": {
|
||||||
|
"flat_json_object": ("JSON",),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
def unflatten_json(self, flat_json_object):
|
||||||
|
return (_unflatten_json_object(flat_json_object),)
|
||||||
|
|
||||||
|
|
||||||
NODE_CLASS_MAPPINGS = {
|
NODE_CLASS_MAPPINGS = {
|
||||||
"DumasJSONStringToObject": DumasJSONStringToObjectNode,
|
"DumasJSONStringToObject": DumasJSONStringToObjectNode,
|
||||||
"DumasJSONObjectToString": DumasJSONObjectToStringNode,
|
"DumasJSONObjectToString": DumasJSONObjectToStringNode,
|
||||||
"DumasJSONGetValue": DumasJSONGetValueNode,
|
"DumasJSONGetValue": DumasJSONGetValueNode,
|
||||||
"DumasJSONSetValue": DumasJSONSetValueNode,
|
"DumasJSONSetValue": DumasJSONSetValueNode,
|
||||||
|
"DumasJSONHasKey": DumasJSONHasKeyNode,
|
||||||
|
"DumasJSONRemoveKey": DumasJSONRemoveKeyNode,
|
||||||
|
"DumasJSONPickFields": DumasJSONPickFieldsNode,
|
||||||
"DumasJSONMergeObjects": DumasJSONMergeObjectsNode,
|
"DumasJSONMergeObjects": DumasJSONMergeObjectsNode,
|
||||||
"DumasJSONKeys": DumasJSONKeysNode,
|
"DumasJSONKeys": DumasJSONKeysNode,
|
||||||
"DumasJSONArrayLength": DumasJSONArrayLengthNode,
|
"DumasJSONArrayLength": DumasJSONArrayLengthNode,
|
||||||
|
"DumasJSONArrayAppend": DumasJSONArrayAppendNode,
|
||||||
|
"DumasJSONArraySlice": DumasJSONArraySliceNode,
|
||||||
"DumasJSONArrayIterator": DumasJSONArrayIteratorNode,
|
"DumasJSONArrayIterator": DumasJSONArrayIteratorNode,
|
||||||
"DumasJSONObjectIterator": DumasJSONObjectIteratorNode,
|
"DumasJSONObjectIterator": DumasJSONObjectIteratorNode,
|
||||||
|
"DumasJSONFlatten": DumasJSONFlattenNode,
|
||||||
|
"DumasJSONUnflatten": DumasJSONUnflattenNode,
|
||||||
}
|
}
|
||||||
|
|
||||||
NODE_DISPLAY_NAME_MAPPINGS = {
|
NODE_DISPLAY_NAME_MAPPINGS = {
|
||||||
@@ -348,9 +601,16 @@ NODE_DISPLAY_NAME_MAPPINGS = {
|
|||||||
"DumasJSONObjectToString": "Dumas JSON Object to String",
|
"DumasJSONObjectToString": "Dumas JSON Object to String",
|
||||||
"DumasJSONGetValue": "Dumas JSON Get Value",
|
"DumasJSONGetValue": "Dumas JSON Get Value",
|
||||||
"DumasJSONSetValue": "Dumas JSON Set Value",
|
"DumasJSONSetValue": "Dumas JSON Set Value",
|
||||||
|
"DumasJSONHasKey": "Dumas JSON Has Key",
|
||||||
|
"DumasJSONRemoveKey": "Dumas JSON Remove Key",
|
||||||
|
"DumasJSONPickFields": "Dumas JSON Pick Fields",
|
||||||
"DumasJSONMergeObjects": "Dumas JSON Merge Objects",
|
"DumasJSONMergeObjects": "Dumas JSON Merge Objects",
|
||||||
"DumasJSONKeys": "Dumas JSON Keys",
|
"DumasJSONKeys": "Dumas JSON Keys",
|
||||||
"DumasJSONArrayLength": "Dumas JSON Array Length",
|
"DumasJSONArrayLength": "Dumas JSON Array Length",
|
||||||
|
"DumasJSONArrayAppend": "Dumas JSON Array Append",
|
||||||
|
"DumasJSONArraySlice": "Dumas JSON Array Slice",
|
||||||
"DumasJSONArrayIterator": "Dumas JSON Array Iterator",
|
"DumasJSONArrayIterator": "Dumas JSON Array Iterator",
|
||||||
"DumasJSONObjectIterator": "Dumas JSON Object Iterator",
|
"DumasJSONObjectIterator": "Dumas JSON Object Iterator",
|
||||||
|
"DumasJSONFlatten": "Dumas JSON Flatten",
|
||||||
|
"DumasJSONUnflatten": "Dumas JSON Unflatten",
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,18 @@
|
|||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
from dumas_json_nodes import (
|
from dumas_json_nodes import (
|
||||||
|
DumasJSONArrayAppendNode,
|
||||||
DumasJSONArrayLengthNode,
|
DumasJSONArrayLengthNode,
|
||||||
DumasJSONArrayIteratorNode,
|
DumasJSONArrayIteratorNode,
|
||||||
|
DumasJSONArraySliceNode,
|
||||||
|
DumasJSONFlattenNode,
|
||||||
DumasJSONGetValueNode,
|
DumasJSONGetValueNode,
|
||||||
|
DumasJSONHasKeyNode,
|
||||||
DumasJSONKeysNode,
|
DumasJSONKeysNode,
|
||||||
DumasJSONMergeObjectsNode,
|
DumasJSONMergeObjectsNode,
|
||||||
|
DumasJSONPickFieldsNode,
|
||||||
|
DumasJSONRemoveKeyNode,
|
||||||
|
DumasJSONUnflattenNode,
|
||||||
DumasJSONObjectIteratorNode,
|
DumasJSONObjectIteratorNode,
|
||||||
DumasJSONObjectToStringNode,
|
DumasJSONObjectToStringNode,
|
||||||
DumasJSONStringToObjectNode,
|
DumasJSONStringToObjectNode,
|
||||||
@@ -48,6 +55,30 @@ class DumasJSONNodeTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(result, ({"user": {"name": "Dumas"}},))
|
self.assertEqual(result, ({"user": {"name": "Dumas"}},))
|
||||||
|
|
||||||
|
def test_has_key_checks_nested_paths(self):
|
||||||
|
node = DumasJSONHasKeyNode()
|
||||||
|
|
||||||
|
result = node.has_key({"user": {"name": "Chris"}}, "user.name")
|
||||||
|
|
||||||
|
self.assertEqual(result, (True,))
|
||||||
|
|
||||||
|
def test_remove_key_removes_nested_values(self):
|
||||||
|
node = DumasJSONRemoveKeyNode()
|
||||||
|
|
||||||
|
result = node.remove_key({"user": {"name": "Chris", "role": "owner"}}, "user.role")
|
||||||
|
|
||||||
|
self.assertEqual(result, ({"user": {"name": "Chris"}},))
|
||||||
|
|
||||||
|
def test_pick_fields_builds_filtered_object(self):
|
||||||
|
node = DumasJSONPickFieldsNode()
|
||||||
|
|
||||||
|
result = node.pick_fields(
|
||||||
|
{"user": {"name": "Chris", "role": "owner"}, "meta": {"active": True}},
|
||||||
|
"user.name\nmeta.active",
|
||||||
|
)
|
||||||
|
|
||||||
|
self.assertEqual(result, ({"user": {"name": "Chris"}, "meta": {"active": True}},))
|
||||||
|
|
||||||
def test_merge_objects_deep_merges_dictionaries(self):
|
def test_merge_objects_deep_merges_dictionaries(self):
|
||||||
node = DumasJSONMergeObjectsNode()
|
node = DumasJSONMergeObjectsNode()
|
||||||
|
|
||||||
@@ -75,6 +106,20 @@ class DumasJSONNodeTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(result, (4,))
|
self.assertEqual(result, (4,))
|
||||||
|
|
||||||
|
def test_array_append_appends_parsed_value(self):
|
||||||
|
node = DumasJSONArrayAppendNode()
|
||||||
|
|
||||||
|
result = node.append_item([1, 2], '{"name":"Dumas"}')
|
||||||
|
|
||||||
|
self.assertEqual(result, ([1, 2, {"name": "Dumas"}],))
|
||||||
|
|
||||||
|
def test_array_slice_returns_subarray(self):
|
||||||
|
node = DumasJSONArraySliceNode()
|
||||||
|
|
||||||
|
result = node.slice_array([0, 1, 2, 3, 4], 1, 4, 2)
|
||||||
|
|
||||||
|
self.assertEqual(result, ([1, 3],))
|
||||||
|
|
||||||
def test_array_iterator_fixed_mode_uses_given_index(self):
|
def test_array_iterator_fixed_mode_uses_given_index(self):
|
||||||
node = DumasJSONArrayIteratorNode()
|
node = DumasJSONArrayIteratorNode()
|
||||||
|
|
||||||
@@ -145,6 +190,20 @@ class DumasJSONNodeTests(unittest.TestCase):
|
|||||||
|
|
||||||
self.assertEqual(result, (None, None, -1, 0))
|
self.assertEqual(result, (None, None, -1, 0))
|
||||||
|
|
||||||
|
def test_flatten_converts_nested_data_to_path_map(self):
|
||||||
|
node = DumasJSONFlattenNode()
|
||||||
|
|
||||||
|
result = node.flatten_json({"user": {"name": "Chris"}, "items": [{"id": 1}]})
|
||||||
|
|
||||||
|
self.assertEqual(result, ({"user.name": "Chris", "items.0.id": 1},))
|
||||||
|
|
||||||
|
def test_unflatten_rebuilds_nested_data(self):
|
||||||
|
node = DumasJSONUnflattenNode()
|
||||||
|
|
||||||
|
result = node.unflatten_json({"user.name": "Chris", "items.0.id": 1})
|
||||||
|
|
||||||
|
self.assertEqual(result, ({"user": {"name": "Chris"}, "items": [{"id": 1}]},))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
|||||||
Reference in New Issue
Block a user