Custom tool json array output is parsed as string #4751

Closed
opened 2026-02-21 18:07:52 -05:00 by yindo · 2 comments
Owner

Originally created by @elvis-cai on GitHub (Jul 24, 2024).

Originally assigned to: @crazywoola on GitHub.

Self Checks

  • This is only for bug report, if you would like to ask a question, please head to Discussions.
  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • 请务必使用英文提交 Issue,否则会被关闭。谢谢!:)
  • Please do not modify this template :) and fill in all the required fields.

Dify version

0.6.11

Cloud or Self Hosted

Self Hosted (Docker)

Steps to reproduce

deploy a custom tool to return json array and test the custom tool to see the output, it's returning text string instead of json format
image

✔️ Expected Behavior

json output is parsed correctly instread of text string format

Actual Behavior

{
  "text": "[{\"description\": \"The image depicts a scenic view of a grassy field with a wooden walkway or boardwalk leading through it. The sky above is mostly clear with some clouds, and there are trees and shrubs visible on either side of the walkway. The overall scene conveys a peaceful, natural environment, likely in a wetland or meadow area.\"}]",
  "files": [],
  "json": []
}
Originally created by @elvis-cai on GitHub (Jul 24, 2024). Originally assigned to: @crazywoola on GitHub. ### Self Checks - [X] This is only for bug report, if you would like to ask a question, please head to [Discussions](https://github.com/langgenius/dify/discussions/categories/general). - [X] I have searched for existing issues [search for existing issues](https://github.com/langgenius/dify/issues), including closed ones. - [X] I confirm that I am using English to submit this report (我已阅读并同意 [Language Policy](https://github.com/langgenius/dify/issues/1542)). - [X] 请务必使用英文提交 Issue,否则会被关闭。谢谢!:) - [X] Please do not modify this template :) and fill in all the required fields. ### Dify version 0.6.11 ### Cloud or Self Hosted Self Hosted (Docker) ### Steps to reproduce deploy a custom tool to return json array and test the custom tool to see the output, it's returning text string instead of json format <img width="460" alt="image" src="https://github.com/user-attachments/assets/cf1f254a-81bd-4263-a0b1-5400fc140a6c"> ### ✔️ Expected Behavior json output is parsed correctly instread of text string format ### ❌ Actual Behavior ``` { "text": "[{\"description\": \"The image depicts a scenic view of a grassy field with a wooden walkway or boardwalk leading through it. The sky above is mostly clear with some clouds, and there are trees and shrubs visible on either side of the walkway. The overall scene conveys a peaceful, natural environment, likely in a wetland or meadow area.\"}]", "files": [], "json": [] }
yindo added the 🐞 bug label 2026-02-21 18:07:52 -05:00
yindo closed this issue 2026-02-21 18:07:52 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Jul 24, 2024):

To ensure that your custom tool's JSON array output is parsed correctly as a JSON array instead of being returned as a text string in Dify version 0.6.11, you need to modify the _invoke method to return the result directly as a JSON object rather than converting it to a string. Here is the modified code:

import json
from typing import Any, Union

from jsonpath_ng import parse

from core.tools.entities.tool_entities import ToolInvokeMessage
from core.tools.tool.builtin_tool import BuiltinTool


class JSONParseTool(BuiltinTool):
    def _invoke(self,
                user_id: str,
                tool_parameters: dict[str, Any],
                ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]:
        """
            invoke tools
        """
        # get content
        content = tool_parameters.get('content', '')
        if not content:
            return self.create_text_message('Invalid parameter content')
        
        # get json filter
        json_filter = tool_parameters.get('json_filter', '')
        if not json_filter:
            return self.create_text_message('Invalid parameter json_filter')

        try:
            result = self._extract(content, json_filter)
            if isinstance(result, str):
                return self.create_text_message(result)
            else:
                return ToolInvokeMessage(result)
        except Exception:
            return self.create_text_message('Failed to extract JSON content')

    # Extract data from JSON content
    def _extract(self, content: str, json_filter: str) -> Any:
        try:
            input_data = json.loads(content)
            expr = parse(json_filter)
            result = [match.value for match in expr.find(input_data)]
            
            if len(result) == 1:
                result = result[0]
            
            if isinstance(result, (dict, list)):
                return result
            elif isinstance(result, (str, int, float, bool)) or result is None:
                return str(result)
            else:
                return repr(result)
        except Exception as e:
            return str(e)

In this modification, the _invoke method checks if the result is a string and returns it as a text message. If the result is not a string (i.e., it is a JSON object or array), it returns it directly as a ToolInvokeMessage. This ensures that JSON arrays are parsed correctly and not returned as text strings [1][2].

To continue talking to Dosu, mention @dosu.

@dosubot[bot] commented on GitHub (Jul 24, 2024): <!-- Answer --> To ensure that your custom tool's JSON array output is parsed correctly as a JSON array instead of being returned as a text string in Dify version 0.6.11, you need to modify the `_invoke` method to return the result directly as a JSON object rather than converting it to a string. Here is the modified code: ```python import json from typing import Any, Union from jsonpath_ng import parse from core.tools.entities.tool_entities import ToolInvokeMessage from core.tools.tool.builtin_tool import BuiltinTool class JSONParseTool(BuiltinTool): def _invoke(self, user_id: str, tool_parameters: dict[str, Any], ) -> Union[ToolInvokeMessage, list[ToolInvokeMessage]]: """ invoke tools """ # get content content = tool_parameters.get('content', '') if not content: return self.create_text_message('Invalid parameter content') # get json filter json_filter = tool_parameters.get('json_filter', '') if not json_filter: return self.create_text_message('Invalid parameter json_filter') try: result = self._extract(content, json_filter) if isinstance(result, str): return self.create_text_message(result) else: return ToolInvokeMessage(result) except Exception: return self.create_text_message('Failed to extract JSON content') # Extract data from JSON content def _extract(self, content: str, json_filter: str) -> Any: try: input_data = json.loads(content) expr = parse(json_filter) result = [match.value for match in expr.find(input_data)] if len(result) == 1: result = result[0] if isinstance(result, (dict, list)): return result elif isinstance(result, (str, int, float, bool)) or result is None: return str(result) else: return repr(result) except Exception as e: return str(e) ``` In this modification, the `_invoke` method checks if the result is a string and returns it as a text message. If the result is not a string (i.e., it is a JSON object or array), it returns it directly as a `ToolInvokeMessage`. This ensures that JSON arrays are parsed correctly and not returned as text strings <sup>[[1]](https://github.com/langgenius/dify/blob/main/api/core/tools/provider/builtin/json_process/tools/parse.py)</sup><sup>[[2]](https://github.com/langgenius/dify/blob/main/api/models/model.py)</sup>. <!-- Dosu Comment Footer --> *To continue talking to [Dosu](https://dosu.dev), mention @dosu.*
Author
Owner

@crazywoola commented on GitHub (Jul 24, 2024):

Link https://github.com/langgenius/dify/issues/6605

@crazywoola commented on GitHub (Jul 24, 2024): Link https://github.com/langgenius/dify/issues/6605
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#4751