diff --git a/dumas_json_nodes.py b/dumas_json_nodes.py index a6c26fc..2a1eabc 100644 --- a/dumas_json_nodes.py +++ b/dumas_json_nodes.py @@ -28,9 +28,9 @@ def _parse_json_path(path): return tuple(segments) -def _get_json_path_value(data, path): +def _get_json_path_value_segments(data, segments): current = data - for segment in _parse_json_path(path): + for segment in segments: if isinstance(segment, int): if not isinstance(current, list) or segment >= len(current): return None @@ -43,9 +43,13 @@ def _get_json_path_value(data, path): return current -def _has_json_path(data, path): +def _get_json_path_value(data, path): + return _get_json_path_value_segments(data, _parse_json_path(path)) + + +def _has_json_path_segments(data, segments): current = data - for segment in _parse_json_path(path): + for segment in segments: if isinstance(segment, int): if not isinstance(current, list) or segment >= len(current): return False @@ -58,16 +62,20 @@ def _has_json_path(data, path): return True +def _has_json_path(data, path): + return _has_json_path_segments(data, _parse_json_path(path)) + + def _build_missing_container(next_segment): return [] if isinstance(next_segment, int) else {} -def _set_json_path_value_recursive(current, segments, value): - if not segments: +def _set_json_path_value_recursive(current, segments, position, value): + if position >= len(segments): return value - segment = segments[0] - is_last = len(segments) == 1 + segment = segments[position] + is_last = position == len(segments) - 1 if isinstance(segment, int): if not isinstance(current, list): @@ -83,8 +91,8 @@ def _set_json_path_value_recursive(current, segments, value): next_current = result[segment] if not isinstance(next_current, (dict, list)): - next_current = _build_missing_container(segments[1]) - updated = _set_json_path_value_recursive(next_current, segments[1:], value) + next_current = _build_missing_container(segments[position + 1]) + updated = _set_json_path_value_recursive(next_current, segments, position + 1, value) if updated is None: return None result[segment] = updated @@ -100,31 +108,34 @@ def _set_json_path_value_recursive(current, segments, value): next_current = result.get(segment) if not isinstance(next_current, (dict, list)): - next_current = _build_missing_container(segments[1]) - updated = _set_json_path_value_recursive(next_current, segments[1:], value) + next_current = _build_missing_container(segments[position + 1]) + updated = _set_json_path_value_recursive(next_current, segments, position + 1, value) if updated is None: return None result[segment] = updated return result -def _set_json_path_value(data, path, value): +def _set_json_path_value_segments(data, segments, value): if not isinstance(data, dict): return None - segments = _parse_json_path(path) if not segments: return value - return _set_json_path_value_recursive(data, segments, value) + return _set_json_path_value_recursive(data, segments, 0, value) -def _remove_json_path_value_recursive(current, segments): - if not segments: +def _set_json_path_value(data, path, value): + return _set_json_path_value_segments(data, _parse_json_path(path), value) + + +def _remove_json_path_value_recursive(current, segments, position): + if position >= len(segments): return _clone_container(current) - segment = segments[0] - is_last = len(segments) == 1 + segment = segments[position] + is_last = position == len(segments) - 1 if isinstance(segment, int): if not isinstance(current, list) or segment >= len(current): @@ -135,7 +146,7 @@ def _remove_json_path_value_recursive(current, segments): del result[segment] return result - updated = _remove_json_path_value_recursive(result[segment], segments[1:]) + updated = _remove_json_path_value_recursive(result[segment], segments, position + 1) if updated is None: return None result[segment] = updated @@ -149,18 +160,21 @@ def _remove_json_path_value_recursive(current, segments): del result[segment] return result - updated = _remove_json_path_value_recursive(result[segment], segments[1:]) + updated = _remove_json_path_value_recursive(result[segment], segments, position + 1) if updated is None: return None result[segment] = updated return result -def _remove_json_path_value(data, path): - segments = _parse_json_path(path) +def _remove_json_path_value_segments(data, segments): if not segments: return _clone_container(data) - return _remove_json_path_value_recursive(data, segments) + return _remove_json_path_value_recursive(data, segments, 0) + + +def _remove_json_path_value(data, path): + return _remove_json_path_value_segments(data, _parse_json_path(path)) def _merge_json_objects(base_object, overlay_object): @@ -211,7 +225,7 @@ def _unflatten_json_object(flat_object): for path, value in flat_object.items(): if not isinstance(path, str): return None - result = _set_json_path_value(result, path, value) + result = _set_json_path_value_segments(result, _parse_json_path(path), value) if result is None: return None return result @@ -369,10 +383,13 @@ class DumasJSONPickFieldsNode: result = {} for raw_path in paths.splitlines(): path = raw_path.strip() - if not path or not _has_json_path(json_object, path): + if not path: continue - value = _get_json_path_value(json_object, path) - result = _set_json_path_value(result, path, value) + segments = _parse_json_path(path) + if not _has_json_path_segments(json_object, segments): + continue + value = _get_json_path_value_segments(json_object, segments) + result = _set_json_path_value_segments(result, segments, value) if result is None: return (None,) return (result,)