JSON to SQL
Paste a JSON sample and get SQL CREATE TABLE statements, instantly and entirely in your browser. Optional fields, nullability and nested types are inferred from the sample — and anything the sample cannot settle is reported rather than guessed.
Type definitions will appear here
Sql create table statements from a sample
Generates one table per object type. A nested object becomes its own table joined by a foreign key, because a relational column cannot hold a nested record. Identifiers that clash with SQL keywords, or that are not valid unquoted, are quoted.
Arrays are stored as JSONB. Whether an array deserves its own table is a modelling decision a sample cannot make for you — as are column lengths and indexes. Review before running.
What a sample cannot tell you
Types are inferred from one sample. A field absent from your sample will be absent from the output, and a field that happens to hold only whole numbers will be typed as an integer even if it can hold decimals. Paste the widest sample you have. For a guarantee rather than an inference, start from a JSON Schema.
What SQL output looks like
Generated from two sample records, one of which has an extra field and a null. This is the actual output, not an illustration:
-- Generated from a JSON sample (PostgreSQL dialect). Review before running:
-- column lengths, indexes, and whether an array deserves its own table
-- are decisions a sample cannot make for you.
CREATE TABLE address (
id BIGSERIAL PRIMARY KEY,
city TEXT NOT NULL,
postcode TEXT
);
CREATE TABLE root (
id BIGINT PRIMARY KEY,
user_name TEXT NOT NULL, -- JSON key: "userName"
is_active BOOLEAN NOT NULL, -- JSON key: "isActive"
score DOUBLE PRECISION NOT NULL,
tags JSONB NOT NULL,
address_id BIGINT NOT NULL,
last_seen TEXT NOT NULL, -- JSON key: "lastSeen"
nickname TEXT,
CONSTRAINT fk_root_address FOREIGN KEY (address_id) REFERENCES address (id)
);
The three things that differ by language
Large integers
A 64-bit identifier becomes BIGINT. Note that the value shown was already rounded by the browser before it reached the generator — if your ids are near 263, treat them as strings end to end.
Optional against nullable
A column is NOT NULL only when the field was present and non-null in every sample. Anything else is left nullable, because a sample cannot prove a constraint.
Names that are not identifiers
Identifiers that clash with SQL keywords, or that are not valid unquoted, are double-quoted. A nested object becomes its own table joined by a foreign key, because a relational column cannot hold a nested record.