Normalize Nested JSON Objects into Multiple SQL Tables
Learn how to decompose nested JSON objects into properly normalized SQL tables with foreign key relationships. Covers 1:1 and 1:N relationships.
Detailed Explanation
From Nested JSON to Normalized Tables
Nested JSON is convenient for APIs but violates relational database normalization rules. The converter decomposes nested objects into separate tables linked by foreign keys.
Example JSON
{
"id": 1,
"name": "Alice",
"email": "alice@example.com",
"address": {
"street": "123 Main St",
"city": "Springfield",
"state": "IL",
"zip": "62701"
},
"orders": [
{ "order_id": 101, "total": 59.99, "status": "shipped" },
{ "order_id": 102, "total": 149.50, "status": "pending" }
]
}
Generated SQL
CREATE TABLE users (
id SERIAL PRIMARY KEY,
name VARCHAR(255) NOT NULL,
email VARCHAR(255) NOT NULL UNIQUE
);
CREATE TABLE addresses (
id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL UNIQUE,
street VARCHAR(255) NOT NULL,
city VARCHAR(255) NOT NULL,
state VARCHAR(50) NOT NULL,
zip VARCHAR(20) NOT NULL,
CONSTRAINT fk_addresses_user FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
);
CREATE TABLE orders (
order_id SERIAL PRIMARY KEY,
user_id INTEGER NOT NULL,
total DECIMAL(10, 2) NOT NULL,
status VARCHAR(50) NOT NULL,
CONSTRAINT fk_orders_user FOREIGN KEY (user_id) REFERENCES orders(id) ON DELETE CASCADE
);
CREATE INDEX idx_orders_user_id ON orders (user_id);
How Nesting Maps to Relationships
| JSON structure | SQL relationship | Example |
|---|---|---|
| Nested object | One-to-One | user → address |
| Array of objects | One-to-Many | user → orders |
| Array of scalars | Junction table or array column | user → tags |
One-to-One Decomposition
A nested object like address becomes a separate table with a UNIQUE foreign key to the parent. The UNIQUE constraint on user_id ensures each user has at most one address.
One-to-Many Decomposition
An array of objects like orders becomes a separate table with a non-unique foreign key. Each order row references the parent user, allowing multiple orders per user.
Normalization Benefits
- No data duplication — The address is stored once, not repeated in every order row.
- Update consistency — Changing a city name updates one row, not dozens.
- Flexible queries — You can query orders independently of users.
- Schema evolution — Adding a field to addresses does not affect the users table.
When to Denormalize
Not every nested object needs its own table. If the sub-object is:
- Always read together with the parent
- Never queried independently
- Has a 1:1 relationship with no reuse
...then storing it as a JSON column or inline columns in the parent table may be simpler. PostgreSQL's JSONB type is excellent for semi-structured sub-documents.
Use Case
You are migrating a NoSQL document store to a relational database and need to decompose nested user documents with embedded addresses and order arrays into properly normalized tables.
Try It — JSON to SQL Schema
Related Topics
Convert JSON Arrays to SQL Junction Tables (Many-to-Many)
Advanced Schemas
Generate Foreign Key Constraints from JSON References
Constraints
Generate SQL Primary Key Constraints from JSON
Constraints
Generate an E-Commerce Database Schema from JSON
Real-World Schemas
Generate a Complete User Table Schema from JSON
Real-World Schemas