Working with Record Location
The record_location setting specifies where to find records within a JSON object fetched by an input connector. It uses GJSON path syntax to traverse and extract data from nested JSON structures.
When to Use
Use record_location when your JSON data wraps the actual records inside a nested structure. For example, if your JSON looks like this:
Code
Setting record_location to data.events extracts the events array, and each element becomes an individual record in your pipeline.
If your records are already at the root level (either a single JSON object or a root-level array), you can leave record_location empty, or set it to @this.
GJSON Path Syntax
Record Location uses GJSON path syntax. Here's a quick reference:
Dot Notation
Use dots to traverse nested objects:
Code
Given this JSON:
Code
| Path | Result |
|---|---|
data | {"events": [{"id": 1, ...}, {"id": 2, ...}]} |
data.events | [{"id": 1, "action": "login"}, {"id": 2, "action": "logout"}] |
Array Access
Access array elements by index:
Code
Using the same JSON above:
| Path | Result |
|---|---|
data.events.0 | {"id": 1, "action": "login"} |
data.events.1 | {"id": 2, "action": "logout"} |
Wildcards
Use * and ? for pattern matching on keys:
Code
Given this JSON:
Code
| Path | Result |
|---|---|
children*.0 | {"name": "Alice"} (first match for keys starting with "children") |
children_??.0 | {"name": "Alice"} (matches "children_us" — two-char wildcard) |
Array Queries
Query arrays for matching elements
Given this JSON:
Code
| Path | Result |
|---|---|
alerts.#(severity=="high") | {"severity": "high", "source": "waf", "message": "SQL injection attempt"} (first match) |
alerts.#(severity=="high")# | [{"severity":"high","source":"waf",...}, {"severity":"high","source":"edr",...}] (all matches) |
alerts.#(source=="waf")#.message | ["SQL injection attempt", "XSS attempt"] |
Note: #(...) returns the first match. #(...)# returns all matches.
Array Iterator (#.)
Use #. to iterate over an array and extract a field from each element:
Code
Given this root-level array:
Code
| Path | Result |
|---|---|
#.id | ["vm-1", "vm-2"] |
#.owner.email | ["alice@co.com", "bob@co.com"] |
#.tags | [["prod","us-east"], ["staging","eu-west"]] (array of arrays) |
#.tags|@flatten | ["prod", "us-east", "staging", "eu-west"] (flattened) |
Modifiers
GJSON supports modifiers that transform results using the pipe (|) operator:
Code
Using the same array above:
| Path | Result |
|---|---|
#.tags|@flatten | ["prod", "us-east", "staging", "eu-west"] |
#.id|@reverse | ["vm-2", "vm-1"] |
Escape Special Characters
Use \ to escape dots in key names:
Code
Given this JSON:
Code
| Path | Result |
|---|---|
app.version | "1.0.0" (traverses into app object) |
app\.version | "2.1.0" (accesses the literal key app.version) |
Examples
Object Storage Inputs (S3, GCS, Azure Blob, B2, etc.)
For object storage connectors, record_location applies only when the format is JSON.
Flat array at root level — leave empty or use @this:
Code
Records nested under a key — use the path to the array:
Code
Code
Deeply nested records:
Code
Code
Extracting a nested field from each element in a root-level array — use #. to iterate:
Code
To stream each cve.foo object as an individual record:
Code
This produces two records: {"id": "uuid-1"} and {"id": "uuid-2"}.
Flattening nested arrays — use #. with |@flatten:
Using the same data above, to stream each object inside the apps arrays as an individual record:
Code
Without @flatten, #.apps would return an array of arrays — each element being the full apps array from one parent object. The @flatten modifier merges them into a single flat array, producing four individual records: {"id": "1"}, {"id": "2"}, {"id": "3"}, {"id": "4"}.
Extracting a specific field from nested array elements — combine #. with |@flatten and another #.:
Code
To stream each finding as an individual record:
Code
This produces three records — one per finding across all parent objects.
GraphQL Inputs
For GraphQL connectors, record_location points to the records array in the GraphQL response. This is typically required since GraphQL responses wrap data under a data key.
Simple response:
Code
Code
Relay-style pagination with edges/nodes:
Code
Code
Quick Reference
| Value | Behavior |
|---|---|
Empty string "" | Treats the entire JSON as a single record, or iterates a root-level array |
@this | Same as empty — refers to the root of the JSON |
@ | Same as @this |
data.events | Extract the events array from inside data |
#.cve.foo | Iterate a root-level array and extract cve.foo from each element |
#.apps|@flatten | Iterate a root-level array, extract apps arrays, and flatten into one list |
data.#.items|@flatten | Same pattern applied to a nested array under data |
Try It Out
You can experiment with GJSON path syntax using the interactive playground at gjson.dev.
For the full GJSON syntax reference, see the GJSON documentation.