The problem: you have JSON, you need rows in a table
An API response, a fixture file, a config export — you've got a JSON array, and you need it as rows in a
database: seeding a dev environment, backfilling a table, or loading test data. Writing the INSERT
statements by hand means escaping every string, remembering which columns are which, and getting the quoting
right for your specific database. For more than a couple of records it's tedious and error-prone.
Fastest path: paste JSON, get INSERT statements
Drop your JSON into the JSON to SQL INSERT Converter. It reads an array of
objects, uses the keys as column names, and emits dialect-aware INSERT statements — MySQL, PostgreSQL,
SQLite, or SQL Server. It can output one statement per row or a single bulk insert, and optionally infer a
CREATE TABLE from the data.
Given:
[
{ "id": 1, "email": "ada@example.com", "active": true, "note": null },
{ "id": 2, "email": "o'brien@example.com", "active": false, "note": "vip" }
]
you get (Postgres):
INSERT INTO your_table (id, email, active, note) VALUES
(1, 'ada@example.com', TRUE, NULL),
(2, 'o''brien@example.com', FALSE, 'vip');
Notice o'brien became o''brien — the single quote was escaped by doubling. That one detail is where
hand-written inserts most often blow up.
The details that decide whether it runs
- String escaping. Single quotes in values must be doubled (
'→'') or the statement breaks — and worse, it's the classic SQL-injection vector if you're building inserts by string concatenation. Let the converter escape; don't hand-glue quotes. - NULL vs empty string vs "null". A JSON
nullshould become the SQL keywordNULL(no quotes), not the string'null'and not''. These three mean different things to the database; getting it wrong corrupts data quietly. - Booleans are dialect-specific. Postgres takes
TRUE/FALSE; MySQL stores them as1/0; SQL Server uses1/0in aBITcolumn. Pick the right target dialect so booleans land correctly. - Numbers stay unquoted.
123is a number;'123'is a string. Quoting a numeric value can force an implicit cast or fail on a strict column. - Nested objects/arrays need a decision. A JSON value that's itself an object or array has no native
scalar SQL type. It gets serialized to a JSON string (for a
JSON/JSONBcolumn) — make sure your target column can hold it, or flatten the data first.
Gotchas worth knowing
- Bulk vs per-row inserts. One multi-row
INSERT ... VALUES (…),(…)is far faster than N single inserts, but if one row fails the whole batch rolls back. For imports where you want partial success, per-row is safer. Choose based on whether you value speed or resilience. - Column order and missing keys. If objects in the array have different keys, decide how gaps are filled (NULL) so every row matches the column list.
- Reserved words and casing. A key like
orderorselectis a reserved word — it may need quoting as an identifier ("order"in Postgres,`order`in MySQL) in both theCREATE TABLEand the insert. - Big files. Tens of thousands of rows are better loaded via
COPY(Postgres) orLOAD DATA(MySQL) than a giantINSERT; use JSON→CSV for that path instead.
When you want a different shape
- Going the other direction — SQL results back to JSON? Use SQL to JSON.
- Need CSV for a bulk-load tool instead of inserts? JSON to CSV.
- Documenting the data in a README? CSV to Markdown table.
Summary
- Paste a JSON array into the JSON to SQL converter, pick your dialect, get runnable inserts.
- The make-or-break details: escape single quotes (
''), map JSONnull→ SQLNULL, keep numbers unquoted, and match booleans to the dialect. - Choose bulk inserts for speed or per-row for partial-success imports.
- For very large loads, go JSON→CSV and use the database's native bulk loader.