Blog Post

The Qrew Blog
4 MIN READ

How to deal with nested lists/arrays in Pipelines?

GeorgiPeev's avatar
GeorgiPeev
Quickbase Staff
7 months ago

Loop through a list of values or entire objects

What are arrays and nested arrays?

If you're building pipelines, then you most likely have encountered query steps and loops.

Query steps in Pipelines produce arrays (also known as "lists") that can be looped through (1). This works seamlessly because the array exists at the top level of the step’s output. 

But what if the array is nested inside a step (2) (not necessarily a query step)... and what if the nested list is compiled of objects (3), not just values?

Many Pipeline builders run into this when integrating with APIs, working with multi-select fields, or processing structured data with parent-child relationship. While Pipelines can loop through arrays, it currently does not support looping through nested arrays. So, below I'll explore how to deal with (2) and (3).

Looping through a nested list of values (2)

A nested array of values may appear as a list but its values are actually stored as:

  • A single value
  • With a delimiter separating each selection (for example ";")
value1; value2; value3; value4

Because of this:

  • Pipelines treats the field as one value
  • You cannot loop through the individual selections directly

A common example of a nested array of values are Multi-select text fields in Quickbase tables.

Solution: Use the “Find all Matches to a Regex” query step

To make a multi-select field "loopable", we first need to extract each value into its own array element.

The Find all Matches to a Regex query step allows you to:

  • Take a nested list of values
  • Apply a regular expression
  • Output a flat array of matches

Once extracted:

  • The output becomes a standard array
  • Pipelines can loop through it natively
  • Each selected value can be processed individually

This is a simple and effective workaround for nested lists that contain only values.

“Find all Matches to a Regex” example

Check out the video.

Use case:

  1. We have a multi-select text field in QB called "multi-select_text".
  2. The record has values "1;3;value1"
  3. I want to loop through each value and check if any records in the table have it for example.

Here is how my pipeline will look like:

  1. Query step to fetch the record (or "Look up a record")
  2. Find all Matches to a Regex step where I'm referencing the "multi-select_text" field and "[^;]+" as my Regular Expression
  3. Loop through each value from "multi-select_text"
  4. Search records step that filters and matches if a record contains any of the values

Looping through a nested list of objects (3)

Things get more complex when the nested list contains objects, not just values.

In this scenario:

  • Each nested object represents a row
  • Each object contains multiple fields
  • You want to insert multiple records into Quickbase
{
  "date": "2025-12-03",
  "invoice_number": "INV-1001",
  "items": [
    {
      "description": "Wireless Mouse",
      "quantity": "2",
      "unit_price": "$15.99",
    },
    {
      "description": "Laptop Stand",
      "quantity": "1",
      "unit_price": "$34.75",
    }
  ]
}

This type of structure is very common when working with APIs and documents — and it’s also where most Pipelines workarounds fall short.

Solution: Use the “Make Request” QB step

To solve this, builders need a "Make Request" Quickbase step with custom Jinja code to process the nested objects.

The step is doing the following:

  • Extracts the information in the nested array
  • Loops through each item in the array
  • Creates a new record in Quickbase for each item
  • Maps the properties of the object to the fields in Quickbase

Check at the end of this article for the full Jinja snippet.

“Make Request” example

Check out the video.

Use case:

  • A user uploads an invoice to Quickbase
  • Top-level invoice data should be stored in a parent table
  • Invoice line items should be stored in a child table related to the parent

Here is how my pipeline will look like:

  1. Trigger step when a user uploads a new invoice in QB
  2. AI Actions step that extracts all the invoice information in a Structured AI Output (JSON Object)
  3. Create record with the top-level invoice information
  4. Make Request step where I'm recording the line items of the invoice and relate them to the top-level invoice info

Final thoughts

Nested arrays are a common part of modern data — especially when working with APIs and AI-generated outputs.

While Pipelines does not currently support looping through nested arrays:

  • Simple nested lists can be handled by reshaping text into arrays
  • Complex nested objects can be processed using Jinja
  • Once the data is flat, Pipelines behaves exactly as expected

Whenever possible, consider recording intermediate data into staging tables to simplify debugging and validation.

The key is understanding how to reshape your data before trying to loop through it.

Full Jinja from example

{
  "to": "XXXX", {# REPLACE WITH TABLE DBID #}
  
{# LIST FIELD NAMES AND IDS FROM QB TABLE #}
  "data": [
    {%- set F = {
      "Description": 6,
      "Qty": 7,
      "Unit Price": 8,
      "TotalAmt": 9,
      "RecordParentId": 12
    } -%}
 
    {# Normalize source: parse if string #}
    {%- set _src = b.output_json | default({}) -%}
    {%- if _src is string -%}
      {%- set _src = _src | from_json -%}
    {%- endif -%}
    {%- set items = _src.items | default([]) -%}
    {%- set _comma = joiner() -%}
    {%- for li in items if li is not none %}
      {%- set desc  = li.description | default('') -%}
      {%- set qty   = li.quantity -%}
      {%- set price = li.unit_price -%}
      {%- set total = li.total_price -%}
 
      {%- if desc != '' or qty is defined or price is defined or total is defined -%} 
      {# MAP EACH FIELD FROM ARRAY TO TABLE (CHECK F VARIABLE) #}
        {{ _comma() }}{
          "{{ F['Description'] }}": { "value": "{{ desc }}" },
 
          "{{ F['Qty'] }}": {
            "value": {{ (qty   | default(0) | string | replace(',', '') | replace('$','')) | float }}
          },
          "{{ F['Unit Price'] }}": {
            "value": {{ (price | default(0) | string | replace(',', '') | replace('$','')) | float }}
          },
 
          "{{ F['TotalAmt'] }}": {
            "value": {{ (total | default(0) | string | replace(',', '') | replace('$','')) | float }}
          },
 
{# PARENT RECORD ID - FROM STEP C IN PIPELINE #}
          "{{ F['RecordParentId'] }}": {
            "value": {{ (c.id | default(0)) | int }} 
          }
        }
      {%- endif -%}
    {%- endfor -%}
  ]
}
Updated 7 months ago
Version 1.0

2 Comments

Comments have been turned off for this post
  • wmcada's avatar
    wmcada
    Qrew Champion

    Good stuff. Please keep this kind of content coming.

    • GeorgiPeev's avatar
      GeorgiPeev
      Quickbase Staff

      As of today, these workaround are no longer needed!!!

      Loops in pipelines can now handle nested lists.