Agent: json
Reads JSON data from a file and inserts rows into the target database table.
Warning
This agent does not create database tables. Target table must already exist.
The target table is determined by task_id.
Typical flow with REST API repeat:
restapi -> creates JSON response files + index file
json -> reads index file, loads JSON files into target table, deletes processed files
Using the same origin file in several JSON actions
json agent consumes files after successful import.
If the same origin file must be processed by several json actions, each action should get its own copy.
Copying repeated API result sets with index files is not supported yet.
Dependency
This agent uses JMESPath for reading JSON values.
Install if needed:
pip install jmespath
Syntax and samples
Basic example:
- do: json
origin:
type: task
file: response.json # normal JSON file
cols:
- name: id
from: data # data, params, extract, const
data: arno_id # JMESPath for params/data/extract, literal value for const
type: int
- name: email
from: data
data: contact.email # nested values use JMESPath
type: text
- name: import_source
from: const
data: manual_file
type: text
Index file example:
- do: json
origin:
type: task
file: unprocessed_files.json # index file from restapi repeat
file_is_index: true # optional, true if origin.file is index file
cols:
- name: jrk
from: params # values from index entry params
data: jrk
type: int
- name: id
from: data # current JSON row
data: arno_id
type: int
- name: email
from: data
data: contact.email
type: text
Child row example:
- do: json
origin:
type: task
file: unprocessed_files.json
file_is_index: true
extract: programs[] # optional, JMESPath for child rows from each data row
cols:
- name: school_id
from: data # parent/root row
data: arno_id
type: int
- name: program_name
from: extract # current child row from extract
data: name
type: text
- name: grades
from: extract
data: grades
type: integer[]
File origin
The JSON file is defined under origin.
origin uses the common file pointer structure. See File pointers.
Required:
origin
origin.type
origin.file
For type: fs, origin.dir is also required.
For type: task, origin.dir is optional. If missing, current task directory is used.
Normal JSON file:
origin:
type: task
file: response.json
Index file:
origin:
type: task
file: unprocessed_files.json
file_is_index: true
Normal JSON file
If file_is_index is missing or false, origin.file is treated as a normal JSON file.
Example JSON:
[
{
"arno_id": 12,
"name": "Tallinna Katse Kool",
"contact": {
"email": "info@katse.ee"
},
"active": true
},
{
"arno_id": 13,
"name": "O'Brien Testkool",
"contact": {},
"active": false
}
]
Example action:
- do: json
origin:
type: task
file: schools.json
cols:
- name: arno_id
from: data
data: arno_id
type: int
- name: nimi
from: data
data: name
type: text
- name: email
from: data
data: contact.email
type: text
- name: aktiivne
from: data
data: active
type: bool
If JSON root is a list of objects, every object becomes one database row.
If JSON root is one object, it becomes one database row.
After successful import, the origin JSON file is deleted.
Index file
If file_is_index: true, origin.file is treated as an index file.
Index file is usually created by restapi repeat logic.
Example unprocessed_files.json:
[
{
"file": "work/routes/test_route/public/schools/restapi_20260721_134739_579796.json",
"params": {
"jrk": 17
}
}
]
Each index entry must have:
file
Optional:
params
params can be used in column mappings with from: params.
Example:
- name: jrk
from: params
data: jrk
type: int
After a response file is successfully imported:
- processed JSON file is deleted;
- entry is removed from index file;
- if index file becomes empty, index file is deleted.
If index file is missing, it is treated as already consumed.
JMESPath
JSON values are read with JMESPath.
Nested object value:
- name: email
from: data
data: contact.email
type: text
Array value:
- name: tags
from: data
data: tags
type: text[]
Full object or list as JSONB:
- name: raw_programs
from: data
data: programs
type: jsonb
Extract
extract is optional.
It is used when target table should be filled from a child structure inside every data row.
Example JSON:
[
{
"arno_id": 12,
"name": "Tallinna Katse Kool",
"programs": [
{
"program_id": 101,
"name": "Põhiõpe",
"grades": [1, 2, 3, 4]
},
{
"program_id": 102,
"name": "Keelekümblus",
"grades": [5, 6, 7]
}
]
},
{
"arno_id": 13,
"name": "Programmita Kool",
"programs": []
}
]
Example action:
- do: json
origin:
type: task
file: schools.json
extract: programs[]
cols:
- name: school_arno_id
from: data
data: arno_id
type: int
- name: school_name
from: data
data: name
type: text
- name: program_id
from: extract
data: program_id
type: int
- name: program_name
from: extract
data: name
type: text
- name: grades
from: extract
data: grades
type: integer[]
This creates one database row for each item in programs.
Values from from: data come from the parent/root row.
Values from from: extract come from the current extracted child row.
If child structure is missing or empty, no rows are inserted for that parent row.
Column definition
Every item in cols describes one target table column.
Required:
name
from
data
Optional:
type
If type is missing, text handling is used.
Column sources
Supported from values:
data
params
extract
const
Value from current JSON row
- name: nimi
from: data
data: name
type: text
Value from nested object
- name: email
from: data
data: contact.email
type: text
Value from index params
Only useful when origin.file_is_index: true.
- name: jrk
from: params
data: jrk
type: int
Value from extracted child row
Only useful when extract is used.
- name: program_name
from: extract
data: name
type: text
Constant value
- name: import_source
from: const
data: restapi_repeat
type: text
SQL expression:
- name: dwh_imported_ts
from: const
data: current_timestamp
type: sql
Supported value types
The type setting controls how JSON/Python values are written into SQL.
Supported values:
text
int, integer
dec, decimal, numeric, float
bool, boolean
json, jsonb
raw, sql
text[], varchar[]
int[], integer[]
dec[], decimal[], numeric[], float[]
bool[], boolean[]
For list or dict values, use json or jsonb when the whole nested structure should be stored:
- name: metadata
from: data
data: metadata
type: jsonb
For simple lists, use PostgreSQL array types:
- name: grades
from: extract
data: grades
type: integer[]
Remarks
- One
jsonaction loads one target table. - The target table name comes from
task_id. - The agent inserts data into existing tables. It does not create or alter table structure.
- Origin JSON root must be one object or a list of objects.
- Scalar root rows are not supported.
- Missing JMESPath value becomes
NULL. extractmust return an object or list.- Missing or empty child list is not an error.
- Normal origin JSON file is deleted after successful import.
- Index file is updated after every successfully processed file.
- Empty index file is deleted.
- Duplicate handling, upsert logic and database constraints are handled outside this agent.
post_actionis not implemented yet.