Skip to content

JSONPath Reference

JSONPath is the notation used to navigate and select data within JSON structures. TinySystems uses JSONPath expressions to access data in your flows.

Root Reference

The $ symbol always refers to the root of the data:

json
// Data
{
  "name": "Alice",
  "age": 30
}
yaml
# Expressions
root: {{$}}              # The entire object
name: "{{$.name}}"       # "Alice"
age: {{$.age}}           # 30

Property Access

Simple Properties

Access object properties with dot notation:

json
{
  "user": "alice",
  "status": "active"
}
yaml
user: "{{$.user}}"       # "alice"
status: "{{$.status}}"   # "active"

Nested Properties

Chain dots for nested access:

json
{
  "user": {
    "profile": {
      "name": "Alice",
      "email": "alice@example.com"
    }
  }
}
yaml
name: "{{$.user.profile.name}}"    # "Alice"
email: "{{$.user.profile.email}}"  # "alice@example.com"

Special Characters

Use bracket notation for properties with special characters:

json
{
  "first-name": "Alice",
  "last name": "Smith",
  "user.id": "12345"
}
yaml
first: "{{$['first-name']}}"   # "Alice"
last: "{{$['last name']}}"     # "Smith"
id: "{{$['user.id']}}"         # "12345"

Array Access

By Index

Arrays are zero-indexed:

json
{
  "items": ["apple", "banana", "cherry"]
}
yaml
first: "{{$.items[0]}}"   # "apple"
second: "{{$.items[1]}}"  # "banana"
third: "{{$.items[2]}}"   # "cherry"

Negative Indices

Count from the end with negative numbers:

yaml
last: "{{$.items[-1]}}"      # "cherry"
secondLast: "{{$.items[-2]}}"  # "banana"

Array of Objects

Access properties within array elements:

json
{
  "users": [
    {"name": "Alice", "age": 30},
    {"name": "Bob", "age": 25}
  ]
}
yaml
firstName: "{{$.users[0].name}}"   # "Alice"
firstAge: {{$.users[0].age}}       # 30
secondName: "{{$.users[1].name}}"  # "Bob"

Array Properties

Length

Get the number of elements:

json
{
  "items": [1, 2, 3, 4, 5]
}
yaml
count: {{$.items.length}}  # 5

Empty Check

yaml
isEmpty: {{$.items.length == 0}}
hasItems: {{$.items.length > 0}}

Complex Paths

Deep Nesting

json
{
  "response": {
    "data": {
      "users": [
        {
          "profile": {
            "contact": {
              "email": "user@example.com"
            }
          }
        }
      ]
    }
  }
}
yaml
email: "{{$.response.data.users[0].profile.contact.email}}"

Mixed Access

Combine dot and bracket notation:

json
{
  "results": [
    {"field-1": "value1"},
    {"field-1": "value2"}
  ]
}
yaml
first: "{{$.results[0]['field-1']}}"   # "value1"
second: "{{$.results[1]['field-1']}}"  # "value2"

Common Data Patterns

HTTP Request Data

json
{
  "method": "POST",
  "path": "/api/users",
  "headers": {
    "Content-Type": "application/json",
    "Authorization": "Bearer token123"
  },
  "body": {
    "name": "Alice",
    "email": "alice@example.com"
  },
  "queryParams": {
    "page": "1",
    "limit": "10"
  }
}
yaml
method: "{{$.method}}"                          # "POST"
contentType: "{{$.headers['Content-Type']}}"    # "application/json"
auth: "{{$.headers.Authorization}}"             # "Bearer token123"
userName: "{{$.body.name}}"                     # "Alice"
page: "{{$.queryParams.page}}"                  # "1"

Nested Arrays

json
{
  "matrix": [
    [1, 2, 3],
    [4, 5, 6],
    [7, 8, 9]
  ]
}
yaml
center: {{$.matrix[1][1]}}   # 5
topRight: {{$.matrix[0][2]}} # 3

Array of Nested Objects

json
{
  "orders": [
    {
      "id": "ord-1",
      "items": [
        {"product": "Widget", "qty": 2},
        {"product": "Gadget", "qty": 1}
      ]
    }
  ]
}
yaml
orderId: "{{$.orders[0].id}}"                    # "ord-1"
firstProduct: "{{$.orders[0].items[0].product}}" # "Widget"
firstQty: {{$.orders[0].items[0].qty}}           # 2

Dynamic Access

Variable Keys

Use bracket notation with expressions:

json
{
  "data": {
    "name": "Alice",
    "age": 30
  },
  "fieldToRead": "name"
}
yaml
# Access field dynamically
value: "{{$.data[$.fieldToRead]}}"  # "Alice"

Computed Indices

json
{
  "items": ["a", "b", "c", "d"],
  "index": 2
}
yaml
item: "{{$.items[$.index]}}"  # "c"

Edge Cases

Missing Properties

When a property doesn't exist, the expression returns undefined:

json
{
  "user": {
    "name": "Alice"
  }
}
yaml
# $.user.email doesn't exist
email: "{{$.user.email}}"  # undefined

# Use default value
email: "{{$.user.email || 'not set'}}"  # "not set"

Null Values

Null is different from undefined:

json
{
  "name": "Alice",
  "nickname": null
}
yaml
nickname: "{{$.nickname}}"              # null
hasNickname: {{$.nickname != null}}     # false
display: "{{$.nickname || $.name}}"     # "Alice"

Empty Arrays

json
{
  "items": []
}
yaml
first: "{{$.items[0]}}"        # undefined
count: {{$.items.length}}      # 0
hasItems: {{$.items.length > 0}}  # false

Path Validation

Check Path Exists

Before accessing deep paths, verify they exist:

yaml
# Risk of error if user or profile doesn't exist
name: "{{$.user.profile.name}}"

# Safer with defaults
name: "{{$.user != null ? $.user.profile.name : 'Unknown'}}"

# Or use default at the end
name: "{{$.user.profile.name || 'Unknown'}}"

Type Checking

Verify expected types:

yaml
# Check if array before accessing
items: "{{Array.isArray($.data) ? $.data : []}}"

# Check if object
value: "{{typeof $.data == 'object' ? $.data.value : null}}"

Performance Tips

Direct Access

Prefer direct paths over complex operations:

yaml
# ✅ Efficient - direct path
name: "{{$.users[0].name}}"

# ⚠️ Less efficient - operations on arrays
# (when you just need one element)

Cache Repeated Access

If you need the same nested value multiple times, consider restructuring your mapping:

yaml
# Instead of repeating deep paths
userName: "{{$.response.data.user.profile.name}}"
userEmail: "{{$.response.data.user.profile.email}}"

# Consider mapping the parent object once
# (in components that support it)

Next Steps

Build flow-based applications on Kubernetes