JSON to SQL INSERT Generator

JSON Input
1
Table Name
SQL INSERT Output

Last updated:

Jsonic's JSON to SQL INSERT generator converts a JSON array of objects into multi-row SQL INSERT statements. Each JSON object becomes one row. String values are single-quoted with internal quotes escaped by doubling. Numbers stay as literals. Booleans become TRUE or FALSE. Null becomes NULL. Nested objects and arrays are serialized as JSON strings. A commented-out CREATE TABLE schema is generated above the INSERT, inferring column types from the first object. The output works with MySQL, PostgreSQL, and SQLite. All processing runs in your browser with no data upload.

How JSON to SQL conversion works

An array of objects maps cleanly onto SQL rows: each object becomes oneINSERT row, each key becomes a column, and each value is cast to a column literal. Rather than emit one statement per object, the generator collapses the whole array into a single multi-row INSERT … VALUES (…), (…) — far fewer round trips to the database.

[
  { "id": 1, "name": "Alice", "age": 30, "active": true,  "notes": null },
  { "id": 2, "name": "Bob",   "age": 25, "active": false, "notes": "new user" }
]
INSERT INTO my_table (id, name, age, active, notes) VALUES
  (1, 'Alice', 30, TRUE,  NULL),
  (2, 'Bob',   25, FALSE, 'new user');

Columns come from the union of all keys

Columns are taken from the keys of the first object. If a later object carries an extra key, scanning only the first row silently drops it; if an object is missing a key, that cell must become NULL so every row has the same arity as the column list. A robust generator takes the union of keys across every object.

[
  { "id": 1, "name": "Alice" },
  { "id": 2, "name": "Bob", "team": "Support" }
]
-- column union: id, name, team
INSERT INTO my_table (id, name, team) VALUES
  (1, 'Alice', NULL),
  (2, 'Bob',   'Support');

Escaping strings, NULL, and booleans

Each JSON type maps to a distinct SQL literal. Strings are single-quoted and any inner single quote is doubled (''') — this is the SQL standard escape, not a backslash. Numbers are bare literals. true/false become TRUE/FALSE, and null becomes an unquoted NULL. Quoting NULL would store the literal text "NULL", a classic bug.

[
  { "msg": "O'Brien said hi", "qty": 3, "shipped": false, "ref": null }
]
INSERT INTO my_table (msg, qty, shipped, ref) VALUES
  ('O''Brien said hi', 3, FALSE, NULL);

Nested objects: JSON string or flattened columns

SQL cells are scalar, so a nested object cannot be stored as-is. The generator serializes nested objects and arrays with JSON.stringify and single-quotes the result, which drops straight into a PostgreSQL JSONB or MySQL JSON column. The alternative is to flatten nested keys into separate columns (address.cityaddress_city) when you query those fields often.

[
  { "id": 1, "name": "Alice", "address": { "city": "Paris", "zip": "75001" } }
]
-- Strategy A: store nested object as a JSONB column (PostgreSQL)
INSERT INTO users (id, name, address) VALUES
  (1, 'Alice', '{"city":"Paris","zip":"75001"}');
SELECT name FROM users WHERE address->>'city' = 'Paris';

-- Strategy B: flatten nested keys into columns
INSERT INTO users (id, name, address_city, address_zip) VALUES
  (1, 'Alice', 'Paris', '75001');

CREATE TABLE and dialect differences

The generator emits a commented-out CREATE TABLE above the INSERT, inferring types from the first object: strings → TEXT/VARCHAR, integers → INTEGER, floats → NUMERIC, booleans → BOOLEAN (or TINYINT(1) in MySQL, which has no native boolean), objects → JSONB/JSON/TEXT. Uncomment it to create the table first. Watch identifier quoting and reserved words like order or group.

-- CREATE TABLE my_table (
--   id     INTEGER PRIMARY KEY,
--   name   TEXT,
--   age    INTEGER,
--   active BOOLEAN,      -- MySQL: TINYINT(1)
--   meta   JSONB         -- MySQL: JSON | SQLite: TEXT
-- );

-- Reserved words must be quoted:
INSERT INTO orders ("order", "group") VALUES (1, 'A');   -- PostgreSQL
INSERT INTO orders (`order`, `group`) VALUES (1, 'A');   -- MySQL

Generate INSERTs in code

When you need conversion in a script or pipeline rather than the browser tool, the core is a per-value formatter. Note the order: in Python bool must be checked before int because bool is a subclass of int. For real applications, prefer the parameterized patterns — they let the driver handle escaping and prevent SQL injection.

# Python — string-building (good for seeds / migrations)
import json

def sql_value(v):
    if v is None:                 return 'NULL'
    if isinstance(v, bool):       return 'TRUE' if v else 'FALSE'  # before int!
    if isinstance(v, (int, float)): return str(v)
    if isinstance(v, (dict, list)): return "'" + json.dumps(v).replace("'", "''") + "'"
    return "'" + str(v).replace("'", "''") + "'"

def json_to_inserts(table, records):
    cols = ', '.join(records[0].keys())
    rows = ',\n  '.join('(' + ', '.join(sql_value(v) for v in r.values()) + ')' for r in records)
    return f"INSERT INTO {table} ({cols}) VALUES\n  {rows};"
// Node.js — same logic in JavaScript
function sqlValue(v) {
  if (v === null || v === undefined) return 'NULL';
  if (typeof v === 'boolean')        return v ? 'TRUE' : 'FALSE';
  if (typeof v === 'number')         return String(v);
  if (typeof v === 'object')         return "'" + JSON.stringify(v).replace(/'/g, "''") + "'";
  return "'" + String(v).replace(/'/g, "''") + "'";
}
# Python — PRODUCTION: parameterized bulk insert (PostgreSQL)
import psycopg2.extras
cols = list(data[0].keys())
rows = [[r.get(c) for c in cols] for r in data]
psycopg2.extras.execute_values(
    cur, f"INSERT INTO users ({', '.join(cols)}) VALUES %s", rows, page_size=1000)

For 100K+ rows, skip INSERT entirely and use PostgreSQL's COPY protocol — 10 to 100 times faster. See the full walkthrough in the Convert JSON to SQL guide. To produce a CSV for \copy first, use the JSON to CSV converter.

How to convert JSON to SQL INSERT statements

  1. Paste a JSON array of objects (or a single JSON object) into the left panel, or click Example to load a sample.
  2. Optionally change the table name (default: my_table).
  3. Click Generate.
  4. Copy the output and run it in your database client (psql, MySQL Workbench, sqlite3, etc.).
  5. Remove the -- comment markers from the CREATE TABLE block if you need to create the table first.

FAQ

What JSON shape does the tool expect?

The tool expects a JSON array of objects, where each object becomes one row in the INSERT statement. It also accepts a single JSON object, which produces a one-row INSERT. All objects should share the same keys — columns are taken from the first object in the array, and missing keys in later rows produce NULL.

How are SQL values escaped?

Strings are single-quoted, with internal single quotes escaped by doubling (so it's becomes 'it''s'). Numbers are written as literals without quotes. Booleans become TRUE or FALSE. JSON null becomes SQL NULL. Nested objects and arrays are serialized to a JSON string and single-quoted.

What databases does the output work with?

The generated multi-row INSERT VALUES syntax is supported by MySQL 5.7+, PostgreSQL 9.4+, and SQLite 3.x. PostgreSQL uses TRUE/FALSE for booleans natively; MySQL also supports 1/0 as boolean literals. The JSON column type (for nested objects) is available in MySQL 5.7+, PostgreSQL (as JSONB), and SQLite 3.38+ with the json extension.

How do I import JSON data into PostgreSQL?

For small datasets, paste the generated INSERT directly into psql or pgAdmin. For large datasets, the COPY command is significantly faster than INSERT — export your JSON to CSV first using jq, then use COPY table FROM file.csv CSV HEADER. For JSON columns specifically, use the JSONB type and cast with ::jsonb.

How do I handle large JSON files?

Most databases have statement-length or parameter-count limits. For thousands of rows, split the JSON array into batches of 500–1000 rows and generate a separate INSERT per batch. MySQL supports LOAD DATA INFILE for CSV imports. PostgreSQL COPY is the fastest bulk-load path. SQLite handles large INSERTs best inside a transaction (wrap with BEGIN; … COMMIT;).

How do I avoid SQL injection with user data?

The generated INSERT is for data migration and seeding workflows only — it is not safe to use as a template for dynamic queries in application code. In application code, always use parameterized queries (prepared statements) and never concatenate user input into SQL strings. The escaping here is for static, trusted data only.

Can I use JSON directly in SQL without converting?

Yes. MySQL has a JSON column type with JSON_EXTRACT() and the ->> operator. PostgreSQL has JSONB with rich operators like ->, ->>, @>, and the jsonb_each() function. SQLite 3.38+ includes json_extract() and related functions. Use native JSON columns when your schema is flexible or when querying nested fields directly in SQL.

How do I convert the CREATE TABLE comment into a real schema?

Remove the -- comment markers at the start of each line and run the resulting CREATE TABLE statement in your database client. Then adjust the inferred types as needed — for example, change TEXT to VARCHAR(255) for known-length strings, INTEGER to SERIAL or BIGINT for auto-incrementing or large IDs, and add PRIMARY KEY, NOT NULL, UNIQUE, and INDEX constraints to match your data model.