One way to this is to use sling. See this blog post which covers loading JSON files into PG.
# in Windows Powershell
$ set POSTGRES 'postgresql://...'
$ sling conns list
+------------+------------------+-----------------+
| CONN NAME | CONN TYPE | SOURCE |
+------------+------------------+-----------------+
| POSTGRES | DB - PostgreSQL | env variable |
+------------+------------------+-----------------+
$ sling run --src-stream file://C:/temp/records.json --tgt-conn POSTGRES --tgt-object public.records --mode full-refresh
11:09AM INF connecting to target database (postgres)
11:09AM INF reading from source file system (file)
11:09AM INF writing to target database [mode: full-refresh]
11:09AM INF streaming data
11:09AM INF dropped table public.records
11:09AM INF created table public.records
11:09AM INF inserted 500 rows in 0 secs [1,556 r/s]
11:09AM INF execution succeeded
Using debug mode would show a DDL of create table if not exists public.records ("data" jsonb). If you would like to flatten your JSON, sling does that as well by adding the --src-options 'flatten: true' option:
$ sling run --src-stream file://C:/temp/records.json --src-options 'flatten: true' --tgt-conn POSTGRES --tgt-object public.records --mode full-refresh
The DDL in that case would be something like:
create table if not exists public.records ("_id" varchar(255),
"age" integer,
"balance" varchar(255),
"company__about" text,
"company__address" varchar(255),
"company__email" varchar(255),
"company__latitude" numeric,
"company__longitude" numeric,
"company__name" varchar(255),
"company__phone" varchar(255),
"company__registered" varchar(255),
"isactive" bool,
"name" varchar(255),
"picture" varchar(255),
"tags" jsonb)
FYI, I am the author of sling.
select * from json_to_record('{"s":"S1","p":"P1","j":"J1","qty":200}') as t(s varchar, p varchar, j varchar, qty integer); s | p | j | qty ----+----+----+----- S1 | P1 | J1 | 200