JSON to MySQL Schema Transformation — Numio
Generates MySQL CREATE TABLE statements from sample JSON. The root becomes a table named generic; each nested object or array becomes a child table with a foreign key to the parent's primary key.
Sketching a normalized table layout for an API payload before writing a real migration.
JSON
MySQL Schema
When to use it
- Sketching a normalized table layout for an API payload before writing a real migration.
- Seeing which nested objects and arrays in a document would need their own tables when moving data from a document store to MySQL.
How to use
- Paste a JSON object, or an array of sample records that are merged into one table, into the left editor, or use the load-file button to open a UTF-8 file.
- Read the generated tables: the root is generic, children are generic_<key>, linked by generic_id foreign keys.
- Copy the SQL, then rename tables and adjust column types (for example DECIMAL for prices or VARCHAR lengths) before running it.
JSON sample object
{
"id": 1024,
"total": 19.5,
"coupon": null,
"created_at": "2026-01-05T10:00:00Z",
"scores": [4, 4.5],
"items": [{ "sku": "A1", "qty": 2 }]
}MySQL CREATE TABLE statements
CREATE TABLE generic ( id INT, total DOUBLE, coupon TEXT, created_at TIMESTAMP, PRIMARY KEY (id) ); CREATE TABLE generic_scores ( generic_id INT, id INT, value DOUBLE, PRIMARY KEY (id), FOREIGN KEY (generic_id) REFERENCES generic(id) ); CREATE TABLE generic_items ( generic_id INT, id INT, sku TEXT, qty INT, PRIMARY KEY (id), FOREIGN KEY (generic_id) REFERENCES generic(id) );
Details and limitations
Integers become INT (BIGINT outside the 32-bit range), other numbers DOUBLE, strings TEXT and booleans BOOLEAN. No VARCHAR lengths, NOT NULL, AUTO_INCREMENT or indexes are generated.
The primary key is a key named id or containing _id; if none exists an id column is added. Strings longer than 18 characters that parse as dates become TIMESTAMP.
null values become TEXT columns. Arrays of scalars get a child table with a value column typed from all elements (scores above is DOUBLE).
Runs in your browser; the output is not validated against a MySQL server.
FAQ
Why is a decimal value typed DOUBLE and not DECIMAL?
The sample cannot show the precision you need, so non-integer numbers become DOUBLE. Change money columns to DECIMAL(p,s) by hand.
Can I choose the table name?
No. The root table is always generic and child tables are generic_<key>. Rename them in the copied SQL.
Does it generate INSERT statements?
No, only CREATE TABLE. To turn JSON rows into INSERT statements use the JSON to SQL tool.