feat: Adding new operations to the Data Operations component#9297
feat: Adding new operations to the Data Operations component#9297Empreiteiro wants to merge 0 commit into
Conversation
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the WalkthroughThe Changes
Sequence Diagram(s)sequenceDiagram
participant User
participant DataOperationsComponent
participant jq Library
User->>DataOperationsComponent: Selects "JSON Query" or "JSON Path" operation
DataOperationsComponent->>DataOperationsComponent: Parse and repair JSON input
DataOperationsComponent->>jq Library: Execute jq query/path extraction
jq Library-->>DataOperationsComponent: Return query/path result
DataOperationsComponent-->>User: Return processed data
Estimated code review effort🎯 4 (Complex) | ⏱️ ~40 minutes Suggested labels
✨ Finishing Touches🧪 Generate unit tests
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. CodeRabbit Commands (Invoked using PR/Issue comments)Type Other keywords and placeholders
Status, Documentation and Community
|
There was a problem hiding this comment.
Actionable comments posted: 4
🔭 Outside diff range comments (2)
src/backend/base/langflow/components/processing/data_operations.py (2)
271-279: Remove duplicate method definition.There are two identical definitions of
operation_exception. The second definition (lines 275-279) will override the first one (lines 271-274).Remove the duplicate:
-def operation_exception(self, operations: list[str]) -> None: - msg = f"{operations} operations are not supported in combination with each other." - raise ValueError(msg) - def operation_exception(self, operations: list[str]) -> None: """Raise exception for incompatible operations.""" msg = f"{operations} operations are not supported in combination with each other." raise ValueError(msg)
387-393: Remove duplicate method definition.There are two identical definitions of
compare_values. The second definition (lines 416-421) will override the first one (lines 387-393).Remove the duplicate at lines 416-421:
-def compare_values(self, item_value: Any, filter_value: str, operator: str) -> bool: - comparison_func = OPERATORS.get(operator) - if comparison_func: - return comparison_func(item_value, filter_value) - return False -Also applies to: 416-421
🧹 Nitpick comments (2)
src/backend/base/langflow/components/processing/data_operations.py (2)
82-95: Consider documenting the list handling limitation.The path extraction only examines the first element of arrays. While this is reasonable for homogeneous lists, it could miss paths in heterogeneous arrays where elements have different structures.
Add a docstring to clarify this behavior:
@staticmethod def extract_all_paths(obj, path=""): + """Extract all possible JSON paths from an object. + + Note: For arrays, only the first element is examined to extract paths. + """ paths = []
227-231: Consider handling missing jq dependency gracefully.The
jqimport inside the method suggests it might be an optional dependency. Consider adding explicit error handling for when it's not installed.def json_query(self) -> Data: import json - import jq + try: + import jq + except ImportError as e: + msg = "The 'jq' library is required for JSON Query operations. Please install it with: pip install jq" + raise ImportError(msg) from e
📜 Review details
Configuration used: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
src/backend/base/langflow/components/processing/data_operations.py(14 hunks)
🧰 Additional context used
📓 Path-based instructions (3)
src/backend/base/langflow/components/**/*.py
📄 CodeRabbit Inference Engine (.cursor/rules/backend_development.mdc)
src/backend/base/langflow/components/**/*.py: Add new backend components to the appropriate subdirectory under src/backend/base/langflow/components/
Implement async component methods using async def and await for asynchronous operations
Use asyncio.create_task for background work in async components and ensure proper cleanup on cancellation
Use asyncio.Queue for non-blocking queue operations in async components and handle timeouts appropriately
Files:
src/backend/base/langflow/components/processing/data_operations.py
{src/backend/**/*.py,tests/**/*.py,Makefile}
📄 CodeRabbit Inference Engine (.cursor/rules/backend_development.mdc)
{src/backend/**/*.py,tests/**/*.py,Makefile}: Run make format_backend to format Python code before linting or committing changes
Run make lint to perform linting checks on backend Python code
Files:
src/backend/base/langflow/components/processing/data_operations.py
src/backend/**/components/**/*.py
📄 CodeRabbit Inference Engine (.cursor/rules/icons.mdc)
In your Python component class, set the
iconattribute to a string matching the frontend icon mapping exactly (case-sensitive).
Files:
src/backend/base/langflow/components/processing/data_operations.py
🧠 Learnings (4)
📚 Learning: applies to src/backend/base/langflow/components/**/__init__.py : update __init__.py with alphabetica...
Learnt from: CR
PR: langflow-ai/langflow#0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/base/langflow/components/**/__init__.py : Update __init__.py with alphabetical imports when adding new components
Applied to files:
src/backend/base/langflow/components/processing/data_operations.py
📚 Learning: applies to src/backend/base/langflow/components/**/*.py : add new backend components to the appropri...
Learnt from: CR
PR: langflow-ai/langflow#0
File: .cursor/rules/backend_development.mdc:0-0
Timestamp: 2025-07-18T18:25:54.486Z
Learning: Applies to src/backend/base/langflow/components/**/*.py : Add new backend components to the appropriate subdirectory under src/backend/base/langflow/components/
Applied to files:
src/backend/base/langflow/components/processing/data_operations.py
📚 Learning: applies to src/backend/tests/**/*.py : test flows using predefined json data and utility functions s...
Learnt from: CR
PR: langflow-ai/langflow#0
File: .cursor/rules/testing.mdc:0-0
Timestamp: 2025-07-21T14:16:14.125Z
Learning: Applies to src/backend/tests/**/*.py : Test flows using predefined JSON data and utility functions such as 'create_flow', 'build_flow', 'get_build_events', and 'consume_and_assert_stream' in backend Python tests.
Applied to files:
src/backend/base/langflow/components/processing/data_operations.py
📚 Learning: when implementing a new component icon in langflow, ensure the icon name is clear, recognizable, and...
Learnt from: CR
PR: langflow-ai/langflow#0
File: .cursor/rules/icons.mdc:0-0
Timestamp: 2025-06-23T12:46:52.420Z
Learning: When implementing a new component icon in Langflow, ensure the icon name is clear, recognizable, and used consistently across both backend (Python 'icon' attribute) and frontend (React/TypeScript mapping).
Applied to files:
src/backend/base/langflow/components/processing/data_operations.py
🪛 GitHub Check: Ruff Style Check (3.13)
src/backend/base/langflow/components/processing/data_operations.py
[failure] 152-152: Ruff (E501)
src/backend/base/langflow/components/processing/data_operations.py:152:121: E501 Line too long (135 > 120)
[failure] 254-254: Ruff (B904)
src/backend/base/langflow/components/processing/data_operations.py:254:13: B904 Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
[failure] 252-252: Ruff (BLE001)
src/backend/base/langflow/components/processing/data_operations.py:252:16: BLE001 Do not catch blind exception: Exception
[failure] 248-248: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:248:34: EM101 Exception must not use a string literal, assign to variable first
[failure] 248-248: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:248:23: TRY003 Avoid specifying long messages outside the exception class
[failure] 245-245: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:245:34: EM101 Exception must not use a string literal, assign to variable first
[failure] 245-245: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:245:23: TRY003 Avoid specifying long messages outside the exception class
[failure] 239-242: Ruff (SIM108)
src/backend/base/langflow/components/processing/data_operations.py:239:13: SIM108 Use ternary operator jq_input = data_json["data"] if isinstance(data_json, dict) and "data" in data_json else data_json instead of if-else-block
[failure] 233-233: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:233:30: EM101 Exception must not use a string literal, assign to variable first
[failure] 233-233: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:233:19: TRY003 Avoid specifying long messages outside the exception class
🪛 GitHub Actions: Ruff Style Check
src/backend/base/langflow/components/processing/data_operations.py
[error] 152-152: Ruff E501: Line too long (135 > 120).
🔇 Additional comments (3)
src/backend/base/langflow/components/processing/data_operations.py (3)
4-5: LGTM! Good choice for JSON repair functionality.The addition of
json_repairimport is appropriate for handling malformed JSON input in the new JSON query operations.
96-118: Excellent implementation of recursive operations!The recursive helper methods for removing and renaming keys are well-designed:
- Properly handle nested dictionaries and lists
- Maintain immutability by creating new objects
- The
rename_keys_recursivecorrectly handles missing keys withdict.get()
121-139: Good configuration for single operation selection.The
limit=1on SortableListInput ensures only one operation can be selected at a time, which correctly aligns with the execution logic inas_data()method.
| name="filter_key", | ||
| display_name="Filter Key", | ||
| info="Key to filter by.", | ||
| info="Name of the key containing the list to filter. It must be a top-level key in the JSON and its value must be a list.", |
There was a problem hiding this comment.
Fix line length violation.
Line exceeds 120 character limit (135 characters).
Break the line to comply with style guide:
- info="Name of the key containing the list to filter. It must be a top-level key in the JSON and its value must be a list.",
+ info=("Name of the key containing the list to filter. "
+ "It must be a top-level key in the JSON and its value must be a list."),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| info="Name of the key containing the list to filter. It must be a top-level key in the JSON and its value must be a list.", | |
| info=("Name of the key containing the list to filter. " | |
| "It must be a top-level key in the JSON and its value must be a list."), |
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)
[failure] 152-152: Ruff (E501)
src/backend/base/langflow/components/processing/data_operations.py:152:121: E501 Line too long (135 > 120)
🪛 GitHub Actions: Ruff Style Check
[error] 152-152: Ruff E501: Line too long (135 > 120).
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/data_operations.py at line
152, the string assigned to the info parameter exceeds the 120 character limit.
Break this long string into multiple concatenated strings or split it across
lines to ensure no single line exceeds 120 characters, maintaining readability
and compliance with the style guide.
| def json_query(self) -> Data: | ||
| import json | ||
|
|
||
| import jq | ||
|
|
||
| if not self.query or not self.query.strip(): | ||
| raise ValueError("JSON Query is required and cannot be blank.") | ||
| raw_data = self.get_data_dict() | ||
| try: | ||
| input_str = json.dumps(raw_data) | ||
| repaired = repair_json(input_str) | ||
| data_json = json.loads(repaired) | ||
| if isinstance(data_json, dict) and "data" in data_json: | ||
| jq_input = data_json["data"] | ||
| else: | ||
| jq_input = data_json | ||
| results = jq.compile(self.query).input(jq_input).all() | ||
| if not results: | ||
| raise ValueError("No result from JSON query.") | ||
| result = results[0] if len(results) == 1 else results | ||
| if result is None or result == "None": | ||
| raise ValueError("JSON query returned null/None. Check if the path exists in your data.") | ||
| if isinstance(result, dict): | ||
| return Data(data=result) | ||
| return Data(data={"result": result}) | ||
| except Exception as e: | ||
| logger.error(f"JSON Query failed: {e}") | ||
| raise ValueError(f"JSON Query error: {e}") | ||
|
|
There was a problem hiding this comment.
Improve exception handling in json_query method.
The exception handling needs improvement based on static analysis findings:
- Avoid catching broad
Exception- be more specific - Use
raise fromto preserve exception chain - Consider extracting error messages to variables
Apply these improvements:
def json_query(self) -> Data:
import json
import jq
if not self.query or not self.query.strip():
- raise ValueError("JSON Query is required and cannot be blank.")
+ msg = "JSON Query is required and cannot be blank."
+ raise ValueError(msg)
raw_data = self.get_data_dict()
try:
input_str = json.dumps(raw_data)
repaired = repair_json(input_str)
data_json = json.loads(repaired)
if isinstance(data_json, dict) and "data" in data_json:
jq_input = data_json["data"]
else:
jq_input = data_json
results = jq.compile(self.query).input(jq_input).all()
if not results:
- raise ValueError("No result from JSON query.")
+ msg = "No result from JSON query."
+ raise ValueError(msg)
result = results[0] if len(results) == 1 else results
if result is None or result == "None":
- raise ValueError("JSON query returned null/None. Check if the path exists in your data.")
+ msg = "JSON query returned null/None. Check if the path exists in your data."
+ raise ValueError(msg)
if isinstance(result, dict):
return Data(data=result)
return Data(data={"result": result})
- except Exception as e:
+ except (json.JSONDecodeError, jq.JQError, ValueError) as e:
logger.error(f"JSON Query failed: {e}")
- raise ValueError(f"JSON Query error: {e}")
+ raise ValueError(f"JSON Query error: {e}") from e📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def json_query(self) -> Data: | |
| import json | |
| import jq | |
| if not self.query or not self.query.strip(): | |
| raise ValueError("JSON Query is required and cannot be blank.") | |
| raw_data = self.get_data_dict() | |
| try: | |
| input_str = json.dumps(raw_data) | |
| repaired = repair_json(input_str) | |
| data_json = json.loads(repaired) | |
| if isinstance(data_json, dict) and "data" in data_json: | |
| jq_input = data_json["data"] | |
| else: | |
| jq_input = data_json | |
| results = jq.compile(self.query).input(jq_input).all() | |
| if not results: | |
| raise ValueError("No result from JSON query.") | |
| result = results[0] if len(results) == 1 else results | |
| if result is None or result == "None": | |
| raise ValueError("JSON query returned null/None. Check if the path exists in your data.") | |
| if isinstance(result, dict): | |
| return Data(data=result) | |
| return Data(data={"result": result}) | |
| except Exception as e: | |
| logger.error(f"JSON Query failed: {e}") | |
| raise ValueError(f"JSON Query error: {e}") | |
| def json_query(self) -> Data: | |
| import json | |
| import jq | |
| if not self.query or not self.query.strip(): | |
| msg = "JSON Query is required and cannot be blank." | |
| raise ValueError(msg) | |
| raw_data = self.get_data_dict() | |
| try: | |
| input_str = json.dumps(raw_data) | |
| repaired = repair_json(input_str) | |
| data_json = json.loads(repaired) | |
| if isinstance(data_json, dict) and "data" in data_json: | |
| jq_input = data_json["data"] | |
| else: | |
| jq_input = data_json | |
| results = jq.compile(self.query).input(jq_input).all() | |
| if not results: | |
| msg = "No result from JSON query." | |
| raise ValueError(msg) | |
| result = results[0] if len(results) == 1 else results | |
| if result is None or result == "None": | |
| msg = "JSON query returned null/None. Check if the path exists in your data." | |
| raise ValueError(msg) | |
| if isinstance(result, dict): | |
| return Data(data=result) | |
| return Data(data={"result": result}) | |
| except (json.JSONDecodeError, jq.JQError, ValueError) as e: | |
| logger.error(f"JSON Query failed: {e}") | |
| raise ValueError(f"JSON Query error: {e}") from e |
🧰 Tools
🪛 GitHub Check: Ruff Style Check (3.13)
[failure] 254-254: Ruff (B904)
src/backend/base/langflow/components/processing/data_operations.py:254:13: B904 Within an except clause, raise exceptions with raise ... from err or raise ... from None to distinguish them from errors in exception handling
[failure] 252-252: Ruff (BLE001)
src/backend/base/langflow/components/processing/data_operations.py:252:16: BLE001 Do not catch blind exception: Exception
[failure] 248-248: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:248:34: EM101 Exception must not use a string literal, assign to variable first
[failure] 248-248: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:248:23: TRY003 Avoid specifying long messages outside the exception class
[failure] 245-245: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:245:34: EM101 Exception must not use a string literal, assign to variable first
[failure] 245-245: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:245:23: TRY003 Avoid specifying long messages outside the exception class
[failure] 239-242: Ruff (SIM108)
src/backend/base/langflow/components/processing/data_operations.py:239:13: SIM108 Use ternary operator jq_input = data_json["data"] if isinstance(data_json, dict) and "data" in data_json else data_json instead of if-else-block
[failure] 233-233: Ruff (EM101)
src/backend/base/langflow/components/processing/data_operations.py:233:30: EM101 Exception must not use a string literal, assign to variable first
[failure] 233-233: Ruff (TRY003)
src/backend/base/langflow/components/processing/data_operations.py:233:19: TRY003 Avoid specifying long messages outside the exception class
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/data_operations.py around
lines 227 to 255, the json_query method currently catches a broad Exception
which is not recommended. Refine the exception handling by catching more
specific exceptions related to JSON processing and jq compilation/execution. Use
'raise from' when re-raising exceptions to preserve the original traceback.
Also, extract the error message into a variable before logging and raising the
new ValueError to improve clarity and maintainability.
| if field_name == "mapped_json_display": | ||
| try: | ||
| parsed_json = json.loads(field_value) | ||
| keys = DataOperationsComponent.extract_all_paths(parsed_json) | ||
| build_config["selected_key"]["options"] = keys | ||
| build_config["selected_key"]["show"] = True | ||
| except Exception as e: | ||
| logger.error(f"Error parsing mapped JSON: {e}") | ||
| build_config["selected_key"]["show"] = False | ||
|
|
There was a problem hiding this comment.
🛠️ Refactor suggestion
Improve exception handling specificity.
The generic exception handling could be more specific to provide better error messages.
if field_name == "mapped_json_display":
try:
parsed_json = json.loads(field_value)
keys = DataOperationsComponent.extract_all_paths(parsed_json)
build_config["selected_key"]["options"] = keys
build_config["selected_key"]["show"] = True
- except Exception as e:
- logger.error(f"Error parsing mapped JSON: {e}")
+ except json.JSONDecodeError as e:
+ logger.error(f"Invalid JSON format: {e}")
+ build_config["selected_key"]["show"] = False
+ except Exception as e:
+ logger.error(f"Unexpected error parsing mapped JSON: {e}")
build_config["selected_key"]["show"] = False📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if field_name == "mapped_json_display": | |
| try: | |
| parsed_json = json.loads(field_value) | |
| keys = DataOperationsComponent.extract_all_paths(parsed_json) | |
| build_config["selected_key"]["options"] = keys | |
| build_config["selected_key"]["show"] = True | |
| except Exception as e: | |
| logger.error(f"Error parsing mapped JSON: {e}") | |
| build_config["selected_key"]["show"] = False | |
| if field_name == "mapped_json_display": | |
| try: | |
| parsed_json = json.loads(field_value) | |
| keys = DataOperationsComponent.extract_all_paths(parsed_json) | |
| build_config["selected_key"]["options"] = keys | |
| build_config["selected_key"]["show"] = True | |
| except json.JSONDecodeError as e: | |
| logger.error(f"Invalid JSON format: {e}") | |
| build_config["selected_key"]["show"] = False | |
| except Exception as e: | |
| logger.error(f"Unexpected error parsing mapped JSON: {e}") | |
| build_config["selected_key"]["show"] = False |
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/data_operations.py around
lines 472 to 481, the current exception handling uses a generic Exception catch
which is too broad. Refine the except block to catch specific exceptions related
to JSON parsing, such as json.JSONDecodeError, to provide more precise error
handling and clearer log messages. Adjust the logger.error call accordingly to
reflect the specific error caught.
| def json_path(self) -> Data: | ||
| try: | ||
| if not self.data or not self.selected_key: | ||
| raise ValueError("Missing input data or selected key.") | ||
| input_payload = self.data[0].data if isinstance(self.data, list) else self.data.data | ||
| compiled = jq.compile(self.selected_key) | ||
| result = compiled.input(input_payload).first() | ||
| if isinstance(result, dict): | ||
| return Data(data=result) | ||
| return Data(data={"result": result}) | ||
| except Exception as e: | ||
| self.status = f"Error: {e!s}" | ||
| self.log(self.status) | ||
| return Data(data={"error": str(e)}) | ||
|
|
There was a problem hiding this comment.
Add missing jq import and improve error handling.
The method uses jq module but doesn't import it. Also, exception handling could be more specific.
def json_path(self) -> Data:
+ import jq
+
try:
if not self.data or not self.selected_key:
raise ValueError("Missing input data or selected key.")
input_payload = self.data[0].data if isinstance(self.data, list) else self.data.data
compiled = jq.compile(self.selected_key)
result = compiled.input(input_payload).first()
if isinstance(result, dict):
return Data(data=result)
return Data(data={"result": result})
- except Exception as e:
+ except jq.JQError as e:
+ self.status = f"Invalid jq expression: {e!s}"
+ self.log(self.status)
+ return Data(data={"error": str(e)})
+ except Exception as e:
self.status = f"Error: {e!s}"
self.log(self.status)
return Data(data={"error": str(e)})📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def json_path(self) -> Data: | |
| try: | |
| if not self.data or not self.selected_key: | |
| raise ValueError("Missing input data or selected key.") | |
| input_payload = self.data[0].data if isinstance(self.data, list) else self.data.data | |
| compiled = jq.compile(self.selected_key) | |
| result = compiled.input(input_payload).first() | |
| if isinstance(result, dict): | |
| return Data(data=result) | |
| return Data(data={"result": result}) | |
| except Exception as e: | |
| self.status = f"Error: {e!s}" | |
| self.log(self.status) | |
| return Data(data={"error": str(e)}) | |
| def json_path(self) -> Data: | |
| import jq | |
| try: | |
| if not self.data or not self.selected_key: | |
| raise ValueError("Missing input data or selected key.") | |
| input_payload = self.data[0].data if isinstance(self.data, list) else self.data.data | |
| compiled = jq.compile(self.selected_key) | |
| result = compiled.input(input_payload).first() | |
| if isinstance(result, dict): | |
| return Data(data=result) | |
| return Data(data={"result": result}) | |
| except jq.JQError as e: | |
| self.status = f"Invalid jq expression: {e!s}" | |
| self.log(self.status) | |
| return Data(data={"error": str(e)}) | |
| except Exception as e: | |
| self.status = f"Error: {e!s}" | |
| self.log(self.status) | |
| return Data(data={"error": str(e)}) |
🤖 Prompt for AI Agents
In src/backend/base/langflow/components/processing/data_operations.py around
lines 484 to 498, the jq module is used but not imported, causing a NameError.
Add an import statement for jq at the top of the file. Also, refine the
exception handling by catching specific exceptions related to jq compilation and
execution instead of a broad Exception to improve error clarity and handling.
|



This PR enhances the DataOperationsComponent by introducing two new powerful operations:
JSON Path: Allows extracting values from nested JSON structures using path expressions, enabling more flexible data selection.
JSON Query: Integrates jq to support advanced JSON queries, including filters, projections, and transformations.
Additional improvements:
Input handling and validations for both new operations.
Enhanced error messages and logs for better debugging.
Extended UI field visibility logic in update_build_config to support dynamic path selection from JSON.
These updates significantly expand the component's capabilities for parsing, transforming, and querying structured JSON data.
Summary by CodeRabbit
New Features
Bug Fixes