Skip to main content
For the complete documentation index for agents and LLMs, see llms.txt.

JsonParser

Extract and parse JSON from text input, handling both plain JSON and Markdown code blocks. This is useful for processing language model outputs that return JSON data wrapped in Markdown formatting.

Key Features​

  • Parses plain JSON strings from text input.
  • Handles JSON wrapped in Markdown code blocks (```json ... ```).
  • Handles JSON wrapped in generic code blocks (``` ... ```).
  • Configurable extraction pattern via a custom regular expression.
  • Returns the parsed JSON as a dictionary for downstream processing.
  • Works with any component that produces text output containing JSON.

Configuration​

  1. Drag the JsonParser component onto the canvas from the Component Library.
  2. Click the component to open the configuration panel.
  3. Configure the parameters as needed.

Connections​

JsonParser accepts a text string (text) as input and outputs the parsed JSON object (parsed_json) as a dictionary.

Typically, JsonParser receives text from a generator such as OpenAIChatGenerator. Because generators output chat messages rather than plain strings, you usually connect an OutputAdapter between the generator and JsonParser to align the types. The parsed_json output then connects to a component like ConditionalRouter that acts on the structured data.

Usage Example​

This is an example of JsonParser that receives text containing JSON from a generator and parses it. There is an OutputAdapter between the generator and JsonParser to align the input and output types of these two components:

components:
OutputAdapter:
type: haystack.components.converters.output_adapter.OutputAdapter
init_parameters:
template: "{{ last_message }}"
output_type: str
custom_filters:
unsafe: false
JsonParser:
type: deepset_cloud_custom_nodes.parsers.json_parser.JsonParser
init_parameters:
code_block_pattern: '```(?:json)?\n(.*?)\n```'
ConditionalRouter:
type: haystack.components.routers.conditional_router.ConditionalRouter
init_parameters:
routes:
- condition: '{{decision.mode == "PASSAGE"}}'
output: '{{history}}'
output_name: followup
output_type: typing.List[haystack.dataclasses.ChatMessage]
- condition: '{{decision.mode == "FRAGE" and decision.complexity in ["simple",
"medium"]}}'
output: '{{decision.query}}'
output_name: search
output_type: str
- condition: '{{decision.mode == "FRAGE" and decision.complexity not in ["simple",
"medium"]}}'
output: '{{history}}'
output_name: agent
output_type: typing.List[haystack.dataclasses.ChatMessage]
- condition: '{{True}}'
output: '{{(history|last).text}}'
output_name: search_last_history
output_type: str
custom_filters: {}
unsafe: false
validate_output_type: false
optional_variables:

LLM:
type: haystack.components.generators.chat.llm.LLM
init_parameters:
chat_generator:
init_parameters:
model: gpt-5.4
type: haystack.components.generators.chat.openai_responses.OpenAIResponsesChatGenerator
system_prompt: >-
{% message role="system" %}

\nDu bist ein exzellentes Labelling-Tool.\nDu bekommst einen
Chatverlauf.\n\n**1. Label Bestimmung**\nFalls die letzte user Frage
nach Informationen aus einer Datenbank sucht, gebe \"FRAGE\" aus.\nDies
ist auch der Fall, wenn etwas erklärt werden soll oder eine Aufgabe
gestellt wird, deren Lösung den Abruf von neuen Informationen erfordert
(z.B. Vergleiche, Tabellen, Analysen erstellen).\n**WICHTIG:** Auch
reine Sachverhaltsschilderungen (z.B. juristische Fälle) ohne explizite
Frage fallen unter das Label \"FRAGE\", da sie implizit nach einer
rechtlichen Einordnung oder ähnlichen Fällen suchen.\n\nFalls die letzte
user Frage Instruktionen sind zum Arbeiten mit einer bereits im
Chatverlauf vorhandenen oder vom User explizit bereitgestellten Passage,
gebe \"PASSAGE\" aus. Dies gilt nur, wenn keine neuen Informationen aus
einer Datenbank abgerufen werden mĂĽssen.\nFalls der Chatverlauf nur eine
user Message enthält, kann nicht das Label \"PASSAGE\" ausgegeben
werden.\nBeispielfragen, welche sich auf die Passage beziehen, sind:
'schreibe davon eine zusammenfassung', 'in stichpunkten' oder
'formuliere als email um'.\n\n**2. Output fĂĽr \"PASSAGE\"**\nFĂĽr das
Label \"PASSAGE\" gibst du NICHTS zusätzlich aus.\nFormat: { \"label\":
\"PASSAGE\" }\n\n**3. Output fĂĽr \"FRAGE\"**\nFĂĽr das Label \"FRAGE\"
gibst du zusätzlich \"query\" und \"complexity\" aus.\n\n**A)
Query-Generierung:**\nDie \"query\" muss in natĂĽrlicher Sprache sein, da
sie von einer keyword und einer semantic search hybrid verarbeitet wird.
Sei daher möglichst explizit mit den Keywords.\n\n**Spezialfall
Sachverhalt:** Wenn der User-Input eine reine Sachverhaltsschilderung
(Fakten, Fallbeispiel) ohne explizite Frage ist, generiere als \"query\"
eine prägnante **Fallbeschreibung**, die die wesentlichen Fakten und
juristischen Probleme zusammenfasst (z.B. \"Fallbeschreibung: Schenkung
unter Auflage, nachträglicher Diebstahl durch Beschenkte und Haftung für
Drittschaden\"). Formuliere in diesem Fall KEINE hypothetischen
Fragen.\n\nWenn nach X auch nach Y gefragt wird, frage in der \"query\"
nur nach Y und wiederhole nicht noch einmal X.\nAbkĂĽrzungen wie
\"ArbVG\", \"BVwG\" oder \"Abs\", sowie alle Paragraphen bleiben
bestehen und dĂĽrfen in der \"query\" nicht umformuliert werden.\nWenn
die Frage keinen Kontext aus der Chat Historie benötigt, gebe sie
unbearbeitet in \"query\" aus.\n\n**B) Komplexitätsbestimmung
(Complexity Analysis):**\nBestimme die Komplexität des Retrievals
(\"complexity\") basierend auf der Schwierigkeit der Anfrage:\n-
**simple**: 1-2 Aspekte/Anspruchsgrundlagen, 1 Themengebiet, klare
Faktenabfrage oder Definition, Standard-Recherche.\n- **medium**: 2-4
Aspekte, 2-3 Themengebiete, Vergleiche zwischen zwei Entitäten, Listen,
abgrenzbare Themen.\n- **high**: 5-7 Aspekte, 3-4 Themengebiete mit
Wechselwirkungen, Synthese aus mehreren Quellen nötig, Abhängigkeiten
(Wenn X, dann Y).\n- **very_high**: ≥8 Aspekte ODER ≥3-stufige
Verschachtelungen ODER systematische WidersprĂĽche ODER sehr abstrakte
Analyseanforderungen.\n\nFormat fĂĽr FRAGE: { \"label\": \"FRAGE\",
\"query\": \"...\", \"complexity\": \"...\" }\n\n\n\n\n{{ message.text
}}\n\n\n\n\n{ \"label\": \"\n

{% endmessage %}
user_prompt: |-
{% message role="user" %}
{{ query }}
{% endmessage %}
required_variables: "*"
streaming_callback:

connections:
- sender: OutputAdapter.output
receiver: JsonParser.text
- sender: JsonParser.parsed_json
receiver: ConditionalRouter.decision
- sender: LLM.last_message
receiver: OutputAdapter.last_message

max_runs_per_component: 100

metadata: {}

inputs:
messages:
- ConditionalRouter.history
- LLM.message
query:
- LLM.query

Parameters​

Inputs​

ParameterTypeDefaultDescription
textstrText containing JSON to parse. Can be plain JSON or JSON wrapped in markdown code blocks.

Outputs​

ParameterTypeDefaultDescription
parsed_jsonDict[str, Any]The parsed JSON object.

Init Parameters​

These are the parameters you can configure in Pipeline Builder:

ParameterTypeDefaultDescription
code_block_patternstr"(?:json)?\\n(.*?)\\n"Regular expression pattern to extract JSON from markdown code blocks. The pattern should include a capture group for the JSON content.

Run Method Parameters​

These are the parameters you can configure for the component's run() method. This means you can pass these parameters at query time through the API, in Playground, or when running a job. For details, see Modify Pipeline Parameters at Query Time.

ParameterTypeDefaultDescription
textstrText containing JSON to parse. Can be plain JSON or JSON wrapped in markdown code blocks.