Skip to content

Introduction

Jinja is a powerful templating engine for Python, extensively used in APIO workflows to dynamically generate JSON structures, manipulate dictionaries, and format output. This guide introduces key features of Jinja, demonstrates APIO-specific extensions, and provides best practices for leveraging Jinja in dynamic workflows.

Examples and exercises can be executed by the reader using the Template Playground, available under the GUI Help menu/Template playground.

Core Concepts in Jinja Templating

Delimiters

  • Used for statements (loops, conditions, etc.):
jinja
{% ... %}
  • Used to print variables or expressions into the output:
jinja
{{ ... }}

Remark

Using -%} instead of %} and {%- instead of {% helps in whitespace control and better formatting

  • Use -%} when you want to strip trailing whitespace or blank lines after a statement.

  • Use {%- when you want to strip leading whitespace before a statement.

  • Use Both: to strip whitespace on both sides of a block or expression for compact output.

Exercise

In the Template Playground, copy paste the following in the Context Panel

json
    {
      "context":{
        "eid": {"value": "12345"},
          "iccid": "",
          "profileType": "test"
      }
    }

In the Template Panel, copy paste the following

jinja
    {
        {% if context.eid %}
          "eid": {{ context.eid }}
        {% endif %}
    }

Click on the “run” button, and check the result. Replace %} with -%}and {% with {%- and check what is changing.

Dynamic JSON Construction

Jinja allows the conditional inclusion of attributes, ensuring only meaningful data is included. For instance, in the example above, If context.eid is non-empty, it is included in the JSON output; otherwise, it is omitted.

Exercise

Change the value of the key “eid”: replace {"value": "12345"} with {}, "", false or null and check the result.

Clarifying the Differences Between JSON Objects and Python Dictionaries

JSON objects and Python dictionaries often seem interchangeable in Jinja templates due to their similar structure and use of {} for key-value pairs. However, there are important distinctions that become particularly significant when working with booleans and null values.

JSON Object

A JSON object is a serialized text format designed for data exchange between systems. Its characteristics include:

  • Language-Independent: JSON is universally supported and follows strict rules.
  • Value Types: JSON values can be:
    • Strings, numbers, booleans (true/false), arrays, objects, or null.
    • Booleans: Represented as true and false (lowercase).
    • Null Values: Represented as null, indicating the absence of a value (equivalent to Python's None).
  • Purpose: Used for transmitting data (e.g., APIs, files).
  • Parsing Required: JSON objects must be parsed into native data structures (e.g., Python dictionaries) before use in programming.

Dictionary

A dictionary is a native Python data structure stored in memory. It is designed for programming logic and data manipulation:

  • Value Types: Python dictionaries can store any Python object as values, including:
    • Strings, numbers, booleans (True/False), None, lists, and other dictionaries.
    • Booleans: Represented as True and False (capitalized).
    • Null Values: Represented as None, a special constant of type NoneType that signifies "no value" or "nothing." In conditional statements, None evaluates to False.
  • Serialization: Dictionaries can be converted to JSON format using serialization when needed.
  • Purpose: Used in Python applications for logic and data manipulation.

Key Difference Between JSON Objects and Dictionaries

FeatureJSON ObjectPython Dictionary
FormatSerialized text for data exchange.In-memory Python data structure.
Boolean Valuestrue, false (lowercase).True, False (capitalized).
Null Valuesnull.None.
UsageFor data transmission (APIs, files).For in-code programming logic.
Parsing/SerializationRequires parsing to become usable.Directly usable in Python; can be serialized.

Truthy and Falsy Values in Jinja

In Jinja (based on Python rules), values are evaluated as truthy or falsy:

  • Falsy Values:

    • False (Python boolean) or false (JSON boolean parsed to Python).
    • None (Python) or null (JSON parsed to Python).
    • 0 (integer or float).
    • Empty strings ("").
    • Empty containers ([], {}, ()).
  • Truthy Values:

    • Everything else, including:
      • Non-empty strings ("hello", "1").
      • Non-zero numbers (42, -1).
      • Non-empty containers ([1, 2, 3], {"key": "value"}).

APIO: Handling JSON Objects as Dictionaries

In APIO, JSON objects are automatically parsed into Python dictionaries before being passed to Jinja templates.

Example

Given the JSON object:

json
{
    "context": {
        "isActive": true
    }
}

This is treated as a Python dictionary in Jinja:

python
{
    "context": {
        "isActive": True
    }
}

Accessing Dictionary Keys in Jinja

In Jinja, you can directly access dictionary keys using dot notation:

jinja
{{ context.isActive }}
  • If context.isActive holds a truthy value, both {{ context.isActive == True }} and {{ context.isActive }} evaluate to True.

Conditional Example

jinja
{% if context.isActive %}
    isActive is True.
{% else %}
    isActive is False.
{% endif %}

If context.isActive contains any truthy value, the output will be:

plaintext
isActive is True.

Dynamically Generating JSON Based on Booleans

If you want to dynamically generate JSON based on the value of {{ context.isActive }}, you can use the | tojson filter in Jinja. This filter ensures proper serialization of Python booleans (True, False) into JSON-compatible booleans (true, false).

Example

Input:

json
{
    "context": {
        "isActive": true
    }
}

Template:

jinja
{
    "result": {{ context.isActive | tojson }}
}

Output:

json
{
    "result": true
}

How It Works

  1. context.isActive:

    • This variable holds a Python boolean (True or False) because APIO converts JSON booleans during parsing.
  2. | tojson Filter:

    • Converts Python True to JSON true and Python False to JSON false, ensuring the output is JSON-compatible.

Summary

  1. JSON vs Dictionary:

    • JSON objects are serialized text formats; dictionaries are in-memory Python structures.
    • JSON true/false → Python True/False; JSON null → Python None.
  2. Truthy and Falsy Values:

    • Jinja evaluates values based on Python truthiness rules. Non-empty strings, non-zero numbers, and non-empty containers are truthy.
  3. APIO Automatic Parsing:

    • APIO converts JSON objects to Python dictionaries, allowing direct access to keys in Jinja templates.
  4. Using | tojson for Serialization:

    • The | tojson filter ensures proper conversion of Python booleans to JSON booleans when generating JSON output dynamically.

Key Dictionaries in APIO Workflows

Among the available Dictionaries in APIO, the following are frequently used

  • context

    • Used to store dynamic data throughout the workflow

    • Example: adding new key-value pairs using the Context Setter cell.

  • request

    • Contains details of the HTTP request, including

      • Body

      • Method

      • Match_info (information from the URL path)

      • Content_type

      • Params (URL parameters)

  • instance

    • Holds metadata about the current workflow instance, including the instance ID