Tighten JSON path helper performance
This commit is contained in:
@@ -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,)
|
||||
|
||||
Reference in New Issue
Block a user