JSON to SQL Converter
Paste JSON or open a .json / .ndjson file and get a CREATE TABLE statement plus INSERT statements for SQL Server, PostgreSQL, MySQL, Oracle or SQLite. A JSON array, a single object, NDJSON and mongoexport output all work. Column types are inferred from every value by the same code Jam SQL Studio's Data Import runs. Nothing is uploaded.
Inferred columns
| Include | Column | SQL type | Null | Notes |
|---|
Generated SQL
Paste JSON, open a file or click one of the Load sample buttons. The inferred columns and the SQL appear here.
What the converter does
It turns JSON rows into a table: every top-level key becomes a column, every object becomes one row, and each column gets a SQL type chosen from all of its values. The output is one CREATE TABLE and the INSERT statements for the rows, written for the engine you pick. It is meant for loading an API response, a mongoexport dump or a JSON fixture into a relational table without writing the DDL by hand, and for checking what types a JSON feed would need before you build the real schema.
The page's script contains Jam SQL Studio's own Data Import code: the type inference, the column-name rules, the CREATE TABLE writer and the literal writer behind the wizard's Generate script instead of executing option. With Rows per INSERT set to 1, the INSERT lines are the text the desktop app writes for the same file, except for these deliberate differences (as of September 2026):
- MongoDB Extended JSON wrappers are unwrapped (you can turn this off); the desktop app keeps them as JSON.
- Columns follow the order in which keys first appear. The desktop app reads each object's keys in JavaScript order, which puts integer-like keys such as
"7"or"2024"first, in numeric order. - A key longer than the engine's identifier limit is cut to that limit; the desktop app keeps the whole key.
- Numbers keep every digit. The desktop app reads decimals and numbers inside nested JSON through a double, and on SQL Server, Oracle and SQLite it also writes
BIGINTandDECIMALvalues above 253 through one, so7212481950938146817becomes7212481950938147000. - Oracle date and time literals are written from the text. The desktop app builds them through a JavaScript
Datein the computer's time zone, so west of UTC a date moves to the day before, a time inside a daylight-saving gap moves forward by the gap, and a time of day comes out asTO_TIMESTAMP('NaN-NaN-NaN…'). - Oracle
timestamp with time zonevalues are written asFROM_TZ(TO_TIMESTAMP(…), 'UTC'). The desktop app's script writes theTO_TIMESTAMPalone, which Oracle reads in the session time zone, so a session at +02:00 stores 08:21:45 UTC as 06:21:45 UTC. - The Oracle
-- WARNINGcomment appears for a text value over 4,000 bytes, the unit of ORA-01704. The desktop app counts characters, so it does not warn about text of 4,000 characters or fewer that accented or non-Latin letters take past 4,000 bytes. - On SQL Server, an ISO date-time written without zero padding or with slashes, such as
2026/3/5 10:15, gets a valid literal; the desktop app cannot parse it.
Getting JSON out of your database or API
MongoDB. mongoexport writes one document per line (JSON Lines) in relaxed Extended JSON. Add --jsonArray for a single array, or --jsonFormat=canonical to wrap every number as $numberInt / $numberLong / $numberDouble. The converter reads all three.
mongoexport --uri="mongodb://localhost:27017/shop" --collection=customers --out=customers.ndjson mongoexport --uri="mongodb://localhost:27017/shop" --collection=customers --jsonArray --out=customers.json
SQL Server. FOR JSON PATH returns an array of objects. It leaves out properties whose value is NULL unless you add INCLUDE_NULL_VALUES; a missing key becomes NULL here anyway, but a column that is NULL in every row would otherwise disappear. Client libraries receive a long FOR JSON result split across several rows, so wrap it in a subquery to get one value.
SELECT ( SELECT order_id, customer, total, placed_at FROM dbo.Orders FOR JSON PATH, INCLUDE_NULL_VALUES ) AS orders_json;
PostgreSQL. row_to_json gives one object per row; psql -At prints each on its own line without headers or padding, which is NDJSON. json_agg builds a single array instead. Avoid \copy ... TO for this: its text format doubles every backslash, which breaks JSON strings that contain escapes.
psql -At -d shop -c "SELECT row_to_json(c) FROM customers c" > customers.ndjson psql -At -d shop -c "SELECT json_agg(c) FROM customers c" > customers.json
MySQL. Build each row with JSON_OBJECT and run the client in batch mode with --raw; without it, batch output escapes backslashes and the JSON no longer parses.
mysql -N -B --raw -e "SELECT JSON_OBJECT('id', id, 'name', name, 'email', email) FROM shop.customers" > customers.ndjsonSQLite. The sqlite3 shell prints a JSON array with -json (SQLite 3.33 and later).
sqlite3 -json app.db "SELECT * FROM customers;" > customers.json
REST APIs. Most responses wrap the rows in an envelope such as {"data": [...], "page": 1}. Paste the whole response and the converter offers a Use “data” as the rows button, or cut the array out first with jq:
curl -s "https://api.example.com/v1/orders?limit=100" | jq '.data' > orders.json curl -s "https://api.example.com/v1/orders?limit=100" | jq -c '.data[]' > orders.ndjson
How column types are inferred
Every non-null value of a column is tested against each candidate type, and the column gets the first candidate in this order that all of its values pass. These are the rules in Jam SQL Studio's Data Import (typeInference.ts and valueTests.ts), unchanged:
- Boolean: JSON
true/false, or the strings"true"/"false"in any case.0/1and"yes"/"no"are not booleans. - 32-bit integer: whole numbers from −2,147,483,648 to 2,147,483,647.
- 64-bit integer: whole numbers in the
BIGINTrange. - Decimal: plain decimals with at most 38 digits. Precision is the widest integer part plus the widest fraction (capped at 38), scale is the widest fraction, so
149.95,32.5and1200giveDECIMAL(6,2). Whole numbers beyond the 64-bit range also land here asDECIMAL(38,0). - Double: a non-zero number smaller than 0.000001 or at least 1021 in absolute value, which JavaScript prints with an exponent (
0.0000001is1e-7), and text such as"1.5e-7". A JSON number is typed by its value, not its spelling:1e5is the integer 100000. - Date:
YYYY-MM-DD(or/), andDD/MM/YYYYorMM/DD/YYYYwith/,-or.. The data decides the order:13/04/2024can only be day/month. When every value fits both orders, as03/04/2024does, no order is assumed and the columns table asks you to choose before anyINSERTis written. - Date-time: a date followed by
HH:MM, optional seconds and fraction. - Date-time with time zone: an ISO date-time ending in
Zor an offset such as+01:00. - Time:
HH:MMorHH:MM:SS. - UUID: 8-4-4-4-12 hexadecimal.
- JSON: any nested object or array, and any string that itself parses as a JSON object or array.
- Text: everything else, sized to the next bucket above the longest value: 50, 100, 255, 1,000 or 4,000 characters, then unbounded.
A value with a leading zero (007) or a leading + is never a number, so ZIP codes and phone numbers stay text. A column is NOT NULL only when every row has a non-null value for it; a missing key counts as NULL. An empty string "" is a value, not NULL, so a numeric column with one "" becomes text. Text with any non-ASCII character becomes a Unicode type on SQL Server (nvarchar). Column names are the keys with surrounding spaces trimmed, inner spaces turned into _, a blank key named after its position (column_2 when it is the second key), duplicates (ignoring case) suffixed _2, and long names cut to the engine's limit (63 characters on PostgreSQL, 64 on MySQL, 128 on SQL Server and Oracle).
| Values | SQL Server | PostgreSQL | MySQL | Oracle | SQLite |
|---|---|---|---|---|---|
| true / false | bit | boolean | tinyint(1) | number(1) | BOOLEAN |
| 32-bit integers | int | integer | int | number(9) | INTEGER |
| 64-bit integers | bigint | bigint | bigint | number(19) | BIGINT |
| decimals | decimal(p,s) | numeric(p,s) | decimal(p,s) | number(p,s) | NUMERIC(p,s) |
| doubles (1e-7, 1e21) | float | double precision | double | binary_double | REAL |
| dates | date | date | date | timestamp | DATE |
| date-times | datetime2 | timestamp | datetime | timestamp | DATETIME |
| date-times with Z / offset | datetimeoffset | timestamp with time zone | timestamp | timestamp with time zone | DATETIME |
| times | time | time | time | timestamp | TIME |
| UUIDs | uniqueidentifier | uuid | char(36) | raw(16) | TEXT |
| nested objects / arrays | json | jsonb | json | json | JSON |
| ASCII text up to 4,000 chars | varchar(n) | character varying(n) | varchar(n) | varchar2(n) | VARCHAR(n) |
| non-ASCII text up to 4,000 chars | nvarchar(n) | character varying(n) | varchar(n) | varchar2(n) | NVARCHAR(n) |
| longer text | varchar(max) / nvarchar(max) | text | TEXT, MEDIUMTEXT or LONGTEXT | clob | TEXT / NTEXT |
The SQL type list in each row of the columns table offers the inferred type plus the common types the desktop wizard offers for that engine. Picking one changes both the CREATE TABLE and how the values are written. JSON strings are then checked against a number, date, time, boolean, UUID or JSON type with the test the desktop app runs when it skips bad rows: if one does not parse ("Ana" in an INTEGER column, say), no INSERTs are written until you pick a wider type. JSON numbers and booleans are not checked, and neither is text length, so 1.5 in an INTEGER column or a 300-character value in nvarchar(255) still gets its INSERT and the database decides what happens to it.
Nested objects and arrays become JSON columns
Only top-level keys become columns. A nested object or array is not flattened into address_city, address_zip and so on; it is written as compact JSON text into one column, exactly as Jam SQL Studio's Data Import stores it. The column type is json on SQL Server, jsonb on PostgreSQL, json on MySQL and Oracle, and JSON on SQLite (where it is a declared type over TEXT). SQL Server's native json type needs SQL Server 2025 or Azure SQL Database, and Oracle's needs Oracle Database 21c or later; on older versions pick nvarchar(max) or CLOB in the SQL type list.
The notes column lists the JSON paths found in the values, for example $.city, $.zip or $[*].sku. A path without [*] works as written in JSON_VALUE on SQL Server, MySQL and Oracle, in json_extract on SQLite and in jsonb_path_query_first on PostgreSQL, whose ->> operator takes a key name instead (address->>'city'). A [*] path matches every element of an array: JSON_VALUE returns NULL for it and SQLite's json_extract rejects it, so use JSON_QUERY with an array wrapper (SQL Server 2025, Oracle), JSON_EXTRACT (MySQL) or jsonb_path_query (PostgreSQL). The SQL JSON Query Builder writes these expressions for each engine.
MongoDB Extended JSON: $oid, $date, $numberLong
mongoexport writes BSON types as wrapper objects. With Unwrap MongoDB Extended JSON ticked (the default), the converter replaces them with plain values before inference, anywhere in the document, and lists how many it unwrapped:
{"$oid": "66f1…"}becomes the 24-character hex string.{"$date": "2025-11-03T08:21:45.120Z"}(relaxed),{"$date": {"$numberLong": "1705311000000"}}(canonical) and{"$date": 1705311000000}become an ISO-8601 UTC timestamp.$numberLong,$numberIntand$numberDoublebecome numbers;$numberLongkeeps every digit.InfinityandNaNstay text because no SQL numeric type holds them.$numberDecimalkeeps its exact digits and scale, so"1249.50"counts as two decimal places.$uuidand$binarywith subtype04become a UUID string. Other binaries,$timestamp,$regularExpressionand anything that is not an exact wrapper stay JSON.
This step exists only in the browser tool. The desktop app's Data Import reads the same file without it, so there each wrapper is a nested object and becomes a JSON column; untick the option to see that result here.
Large integers and exact decimals
JavaScript's JSON.parse stores every number as a double, which holds integers exactly only up to 253 (9,007,199,254,740,992). A 64-bit ID such as 7212481950938146817 comes out as 7212481950938147000, and a converter built on JSON.parse writes that wrong ID into your INSERT. This page reads numbers from the raw text instead, the way the desktop app's JSON reader does for top-level integers, and writes the exact digits of any number a double cannot hold, including long decimals and numbers inside nested JSON text. When a BIGINT or DECIMAL column holds such numbers, a note above the columns table names the column and shows what JSON.parse would make of the first one. A column typed as a double rounds them anyway, so it gets no note.
In the SQL, SQL Server, Oracle and SQLite get the digits as a bare number and PostgreSQL and MySQL as quoted text that the server casts, so a BIGINT or DECIMAL column on SQL Server, PostgreSQL, MySQL and Oracle receives the value you exported; SQLite's NUMERIC storage rounds some of them (see Limitations). Inside a JSON column the digits are part of the text, but MySQL's JSON type stores a number with a fraction or beyond the 64-bit range as a double. Numbers a double does hold exactly are read as numbers, so trailing zeros are dropped: 10.50 is read as 10.5 and counts as one decimal place. Quote such values in the JSON, or export them as $numberDecimal, when the scale matters.
Example: a JSON array to SQL Server
The Load sample: JSON array input, three orders shaped like a REST API response (synthetic data):
[
{ "order_id": 1001, "customer": "Ana Souza", "email": "[email protected]", "total": 149.95, "paid": true,
"placed_at": "2026-03-02T09:14:00Z", "ship_by": "2026-03-04",
"items": [{ "sku": "KB-104", "qty": 1 }, { "sku": "MS-220", "qty": 2 }], "coupon": null },
{ "order_id": 1002, "customer": "Jörg Müller", "email": "[email protected]", "total": 32.5, "paid": false,
"placed_at": "2026-03-02T11:40:12Z", "ship_by": "2026-03-06",
"items": [{ "sku": "CB-310", "qty": 3 }], "coupon": "SPRING10" },
{ "order_id": 1003, "customer": "Liam O'Connor", "email": "[email protected]", "total": 1200, "paid": true,
"placed_at": "2026-03-03T16:05:47Z", "ship_by": "2026-03-05", "items": [], "coupon": null }
]The output for SQL Server with the default options, unedited:
-- Generated in your browser by the free JSON to SQL converter on jamsql.com -- SQL Server · 3 rows · 9 columns CREATE TABLE [orders] ( [order_id] int NOT NULL, [customer] nvarchar(50) NOT NULL, [email] varchar(50) NOT NULL, [total] decimal(6,2) NOT NULL, [paid] bit NOT NULL, [placed_at] datetimeoffset NOT NULL, [ship_by] date NOT NULL, [items] json NOT NULL, [coupon] varchar(50) ); INSERT INTO [orders] ([order_id], [customer], [email], [total], [paid], [placed_at], [ship_by], [items], [coupon]) VALUES (1001, N'Ana Souza', N'[email protected]', 149.95, 1, N'2026-03-02T09:14:00.000Z', N'2026-03-04T00:00:00.000Z', N'[{"sku":"KB-104","qty":1},{"sku":"MS-220","qty":2}]', NULL); INSERT INTO [orders] ([order_id], [customer], [email], [total], [paid], [placed_at], [ship_by], [items], [coupon]) VALUES (1002, N'Jörg Müller', N'[email protected]', 32.5, 0, N'2026-03-02T11:40:12.000Z', N'2026-03-06T00:00:00.000Z', N'[{"sku":"CB-310","qty":3}]', N'SPRING10'); INSERT INTO [orders] ([order_id], [customer], [email], [total], [paid], [placed_at], [ship_by], [items], [coupon]) VALUES (1003, N'Liam O''Connor', N'[email protected]', 1200, 1, N'2026-03-03T16:05:47.000Z', N'2026-03-05T00:00:00.000Z', N'[]', NULL);
What to notice: customer is nvarchar because of Jörg Müller while the all-ASCII email is varchar; total is decimal(6,2) from the widest integer part (1200) and fraction (149.95); the items array stays one json column; coupon is nullable because two rows have null; and the apostrophe in O'Connor is doubled. Every string literal carries the N prefix so Unicode survives the insert.
Example: mongoexport output to PostgreSQL
The Load sample: mongoexport input is mongoexport's default format, one relaxed Extended JSON document per line. The third customer has no device_id.
{"_id":{"$oid":"66f1c2a4e13b7a5d9c8e4a01"},"name":"Ana Souza","email":"[email protected]","signup":{"$date":"2025-11-03T08:21:45.120Z"},"plan":"pro","balance":{"$numberDecimal":"1249.50"},"device_id":7212481950938146817,"address":{"city":"Lisboa","zip":"1100-148"},"tags":["beta","newsletter"]}
{"_id":{"$oid":"66f1c2a4e13b7a5d9c8e4a02"},"name":"Jörg Müller","email":"[email protected]","signup":{"$date":"2026-01-17T14:02:09.000Z"},"plan":"free","balance":{"$numberDecimal":"0.00"},"device_id":7212481950938146818,"address":{"city":"München","zip":"80331"},"tags":[]}
{"_id":{"$oid":"66f1c2a4e13b7a5d9c8e4a03"},"name":"Liam O'Connor","email":"[email protected]","signup":{"$date":"2026-02-28T19:45:00.500Z"},"plan":"pro","balance":{"$numberDecimal":"87.25"},"address":{"city":"Dublin"},"tags":["newsletter"]}The output for PostgreSQL with Rows per INSERT set to 100:
-- Generated in your browser by the free JSON to SQL converter on jamsql.com
-- PostgreSQL · 3 rows · 9 columns
CREATE TABLE "customers" (
"_id" character varying(50) NOT NULL,
"name" character varying(50) NOT NULL,
"email" character varying(50) NOT NULL,
"signup" timestamp with time zone NOT NULL,
"plan" character varying(50) NOT NULL,
"balance" numeric(6,2) NOT NULL,
"device_id" bigint,
"address" jsonb NOT NULL,
"tags" jsonb NOT NULL
);
INSERT INTO "customers" ("_id", "name", "email", "signup", "plan", "balance", "device_id", "address", "tags") VALUES
('66f1c2a4e13b7a5d9c8e4a01', 'Ana Souza', '[email protected]', '2025-11-03T08:21:45.120Z', 'pro', '1249.50', '7212481950938146817', '{"city":"Lisboa","zip":"1100-148"}', '["beta","newsletter"]'),
('66f1c2a4e13b7a5d9c8e4a02', 'Jörg Müller', '[email protected]', '2026-01-17T14:02:09.000Z', 'free', '0.00', '7212481950938146818', '{"city":"München","zip":"80331"}', '[]'),
('66f1c2a4e13b7a5d9c8e4a03', 'Liam O''Connor', '[email protected]', '2026-02-28T19:45:00.500Z', 'pro', '87.25', NULL, '{"city":"Dublin"}', '["newsletter"]');The three $oid, $date and $numberDecimal wrappers are gone, balance keeps its two decimal places, device_id keeps all 19 digits and is nullable because the third document lacks it, and address and tags are jsonb. Before publishing, both examples and a set of edge cases (64-bit IDs, a 20-digit integer, a 19-digit decimal, UUIDs, times of day, day/month dates, date-times inside daylight-saving gaps and date-times with offsets, with Oracle's session time zone set to +02:00) were run, at 1 and 100 rows per INSERT, against SQL Server 2025, PostgreSQL 16, MySQL 8.0, Oracle AI Database 26ai Free and SQLite 3.46 on 23 September 2026.
Supported input and limits
- Shapes: a JSON array of objects; a single object; NDJSON / JSON Lines (one object per line); objects written one after another, even pretty-printed. Every row must be an object: an array of numbers or strings is rejected with the row number. A single object whose property holds an array of objects gets a button to use that array as the rows. A UTF-8 byte-order mark is ignored.
- Size: 5 MiB of input and 20,000 rows per run. More rows are counted and reported, and only the first 20,000 are written. Nesting is limited to 512 levels.
- Rows per INSERT: 1 (the desktop app's script format), 10, 100, 500 or 1,000. 1,000 is SQL Server's limit for a
VALUESlist (error 10738) and is used as the ceiling everywhere; a statement is also split before it passes 4,000,000 bytes. Oracle always gets one row perINSERT, because multi-rowVALUESonly arrived in Oracle Database 23ai. - Oracle literals: Oracle caps a string literal at 4,000 bytes (ORA-01704), which is fewer than 4,000 characters when the text has accented or non-Latin letters. A row with a longer text value still gets its
INSERT, preceded by a-- WARNINGcomment. The converter counts UTF-8 bytes, the encoding of Oracle's default AL32UTF8 character set. - Output: the SQL pane shows at most the first 200,000 characters, cut at the end of a line; Copy and Download always carry the whole script.
Everything stays in your browser
The converter is one script, /js/tools/json-to-sql.js, and the JSON you paste or open is parsed and converted by it in memory. It is not sent to a server, not placed in the URL, and not written to localStorage or sessionStorage; Download .sql builds the file in the page. The page also loads what every jamsql.com page loads: small inline menu and image-zoom code, /js/jam-events.js, and the Umami and Google Ads tags, which see the page view but not your input. The analytics events are these, with no keys, values, table names or file names in them:
tool-json-to-sql-load-samplewithsample:arrayormongoexport.tool-json-to-sql-open-filewhen you pick a file, with no properties.tool-json-to-sql-generateonce per new input, when its SQL is first generated, withengine,form(array,object,ndjsonornested-array),rowsas a bucket (1-10,11-100,101-1000,1001-10000or10001+) andextendedJson(yesorno).tool_sql_exportwhen you copy or download the SQL, withtool:json-to-sql,outcome:copyordownload, and the page path.- On the links:
download_page_clickandtool_product_clickfrom the Get Jam SQL Studio and Data Import docs links (page, placement, target OS or tool and destination kind), andtool-json-to-sql-download-ctafrom the Download Free button.
Clear empties the input, the notices, the columns table and the SQL, and resets a table name that came from a file name or a sample; a name you typed stays.
Limitations
- Types are inferred from the rows you paste, not from your real schema. Fifty numeric codes do not prove the next file has no letters in them.
- No primary key, index or foreign key is guessed. Add them after the
CREATE TABLE. - Nested values are not flattened into separate columns; query them with the engine's JSON functions.
- Identifiers are always quoted and keep their case. On Oracle a lower-case table such as
"customers"has to be quoted in every query, and on PostgreSQL so does a key likecustomerId. - The script has no transaction around it and no
GOseparators. For all or nothing, putBEGIN;before it andCOMMIT;after it on PostgreSQL and SQLite, andSET XACT_ABORT ON; BEGIN TRANSACTION;…COMMIT TRANSACTION;on SQL Server (withoutXACT_ABORTan error does not roll the transaction back). MySQL and Oracle commit aCREATE TABLEas soon as it runs, so only theINSERTs can be undone: wrap them inSTART TRANSACTION;…COMMIT;on MySQL, and on Oracle run the script in SQL*Plus afterWHENEVER SQLERROR EXIT ROLLBACK, orROLLBACKby hand after an error. - MySQL
datetime,timestampandtimecolumns are created without fractional seconds, so MySQL rounds19:45:00.500to19:45:01and08:30:15.600to08:30:16. Date-times withZor an offset go into atimestampcolumn, which only holds 1970-01-01 00:00:01 to 2038-01-19 03:14:07 UTC; a later value fails with error 1292. - Oracle stores an empty string as
NULL, so aNOT NULLtext column that has""in some rows fails with ORA-01400; removeNOT NULLfrom theCREATE TABLEfor it. Andvarchar2(n)counts bytes, so text with accented or non-Latin letters can pass the limit (ORA-12899: thirtyéare 60 bytes in avarchar2(50)); pickVARCHAR2(255)orCLOBin the SQL type list. - Oracle has no time-of-day type: times are stored as a
timestampon 1970-01-01. A date-time with an offset keeps its instant but not its offset: SQL Server stores it at+00:00, Oracle in UTC, PostgreSQL and MySQL convert it to UTC, and only SQLite keeps the text as written. - SQLite stores a
NUMERICvalue as an 8-byte integer or float, so it rounds whole numbers beyond the 64-bit range and decimals with more than about 15 significant digits on its own; declare the columnTEXTif every digit matters. INSERTscripts are the slow way to load big data. For recurring or large loads useCOPY,BULK INSERT,LOAD DATA, SQL*Loader, or the desktop app's Data Import.
Frequently asked questions
How do I convert JSON to SQL INSERT statements?
Paste a JSON array of objects, a single object or NDJSON into the converter above, or open a .json or .ndjson file. Pick SQL Server, PostgreSQL, MySQL, Oracle or SQLite, set the table name, then copy or download the script. Each top-level key becomes a column and each object becomes one row, with column types inferred from every value.
What happens to nested objects and arrays?
They are not flattened. Each nested object or array is written as compact JSON text into one column, typed json on SQL Server, jsonb on PostgreSQL and JSON on MySQL, Oracle and SQLite. Jam SQL Studio's Data Import maps JSON files the same way, and you can read single fields later with JSON_VALUE, the ->> operator or json_extract.
Can I convert mongoexport output?
Yes. mongoexport writes one document per line by default and a single array with --jsonArray; both are accepted. The converter unwraps MongoDB Extended JSON such as $oid, $date, $numberLong and $numberDecimal into plain values, so _id becomes a text column and dates become timestamps. Untick the option to keep the wrappers as JSON, which is what the desktop app's Data Import does.
Are large integer IDs kept exactly?
Yes. The converter reads numbers from the raw text instead of through JavaScript's JSON.parse, which would turn 7212481950938146817 into 7212481950938147000. BIGINT and DECIMAL values keep every digit in the generated literals on all five engines, and the page tells you which columns held such values.
Is my JSON uploaded anywhere?
No. The JSON is parsed and converted by JavaScript running in this page, kept in memory only, and never sent to a server, put in the URL or written to browser storage. Analytics record which sample or engine you used, the input shape, a row-count bucket, whether Extended JSON was unwrapped, that you opened a file, and whether you copied or downloaded the SQL, never keys, values, table names or file names.
How many rows can I convert at once?
Up to 5 MiB of JSON and 20,000 rows per run. With more rows the converter writes the first 20,000 and reports the total, for example the first 20,000 of 35,000 rows. For bigger files, Jam SQL Studio's Data Import reads JSON and NDJSON from disk as a stream and inserts the rows directly; the free Personal licence imports up to 100,000 rows per run.
Why are PostgreSQL and MySQL values written as quoted text?
The converter uses the same literals Jam SQL Studio writes in its script mode: PostgreSQL and MySQL get quoted text such as '1001', and the server casts it to the column type. An integer column stores 1001, and BIGINT or NUMERIC values keep every digit because they never pass through a floating-point number.
Loading JSON into a real database?
Jam SQL Studio is a free desktop SQL client for SQL Server, PostgreSQL, MySQL, Oracle and SQLite. Its Data Import wizard loads JSON, NDJSON, CSV and Excel files into new or existing tables, and the grid lets you browse and filter the JSON columns afterwards.
Free for personal use • No account required • Mac, Windows, Linux
More free SQL tools
CSV to SQL Converter
Paste CSV or spreadsheet data and get INSERT statements or a CREATE TABLE script with inferred column types.
CSV to JSON Converter
Paste or upload CSV and get a pretty-printed JSON array or NDJSON, with numbers and booleans inferred per column.
Excel to SQL Converter
Upload an .xlsx workbook and get INSERT statements or a CREATE TABLE script, with a sheet picker.
Jam SQL Studio