---
url: https://findutils.com/guides/json-to-sql
title: "Convert JSON to SQL INSERT Statements Without Losing Types"
description: "Convert a JSON array to SQL for PostgreSQL, MySQL or SQLite. Learn how types are inferred, why the CSV route damages booleans and null, and what nesting cannot do."
category: converters
content_type: guide
guide_type: subtopic
cluster: data-conversion
locale: en
read_time: 6
status: published
author: "olgunozoktas"
published_at: 2026-09-02T09:30:00Z
excerpt: "Turn an API response or a fixture into CREATE TABLE and INSERT statements. Review type inference, NULL handling, dialect rules, and how nested objects are stored."
tag_ids: ["json", "sql", "data-conversion", "postgresql", "database"]
tags: ["JSON", "SQL", "Data Conversion", "PostgreSQL", "Database"]
primary_keyword: "json to sql"
secondary_keywords: ["convert json to sql", "json to insert statements", "json to create table", "json array to sql", "json to postgresql", "ndjson to sql"]
tool_tag: "json-to-sql"
related_tool: "json-to-sql"
related_tools: ["json-to-sql", "csv-to-sql", "json-to-csv"]
og_image: "/images/content/guides/json-to-sql-type-preservation.webp"
image_alt: "A nested JSON structure passes through a type-preserving conversion gate into three database outputs."
updated_at: "2026-09-08T09:09:24Z"
---

Convert JSON to SQL by reading each value's real type instead of its text. FindUtils [JSON to SQL](/convert/json-to-sql/) turns an array of objects into `CREATE TABLE` plus `INSERT` statements for PostgreSQL, MySQL or SQLite, in your browser. It does not upload the JSON and it does not connect to a database.

This guide explains how column types are decided, why the popular JSON-to-CSV-to-SQL workaround damages data, and where the tool deliberately stops.

## Why Not Just Go Through CSV?

The two-hop route — [JSON to CSV](/convert/json-to-csv/), then [CSV to SQL](/convert/csv-to-sql/) — is the reason this tool exists, so it is worth being precise about what it costs.

CSV has exactly one type: text. JSON has four that matter here. Everything that is not a string has to be flattened on the way through, and there is no way to tell afterwards what it used to be.

| JSON value | After the CSV hop | Direct |
|---|---|---|
| `true` | `'true'` — a string | `TRUE` |
| `null` | `'null'` or `''` | `NULL` |
| `{"a":1}` | `'[object Object]'` | `'{"a":1}'` |
| `1.5` | usually survives | `1.5` |

The `[object Object]` case is the one people notice, because it is visibly broken. The boolean and null cases are worse: they look fine, import cleanly, and quietly give you a text column where you expected a boolean.

For a flat array of strings and numbers the CSV route is perfectly good. The moment a value is a boolean, a null, or nested, it is the wrong tool.

## How to Convert JSON to SQL Online

### Step 1: Open the JSON to SQL Tool

Go to [JSON to SQL](/convert/json-to-sql/). Use a synthetic API payload for the first conversion, then review the inferred types.

### Step 2: Paste the JSON

An array of objects is the normal input. A single object is treated as one row, and NDJSON — one object per line — is accepted too; it is tried automatically if the whole paste is not valid JSON on its own.

### Step 3: Name the Table

The table name is the only field you have to fill in. It is quoted for the dialect you pick, so a name with unusual characters is still safe.

### Step 4: Pick the Dialect

PostgreSQL, MySQL or SQLite. The choice changes identifier quoting, the type names in the `CREATE TABLE`, and how booleans are written.

### Step 5: Review the Inferred Types

The line under the output names every column and its type. Read it before you run anything — this is where a surprise shows up.

### Step 6: Copy or Download

Copy the SQL, or download it as a `.sql` file.

## How Types Are Inferred

Each column is decided across every row, not from the first one.

- Whole numbers give an integer column.
- A decimal anywhere widens that column to numeric.
- `true` and `false` give a boolean column.
- Anything else, including a mix of a boolean and a number, gives text.
- **A null never decides anything.** A column of nulls and integers is an integer column.

That last rule is the one that saves you. If a null narrowed the type, one missing field in one row would turn a numeric column into text.

Booleans depend on the dialect. SQLite has no boolean literal, so it gets `1` and `0`; PostgreSQL and MySQL get `TRUE` and `FALSE`.

## Rows With Different Keys

The columns are the union of every key across every row, in the order the keys are first seen. A row that lacks one of them gets `NULL` for that column.

```json
[{"a": 1}, {"b": 2}]
```

becomes a table with both `a` and `b`, and two rows: `(1, NULL)` and `(NULL, 2)`. Nothing is clipped, and nothing is invented.

One thing SQL cannot express: a key that is missing and a key explicitly set to `null` both become `NULL`. There is no third state to map them to.

## Nested Objects and Arrays

A nested object or array is stored as its JSON text in one column. It is never `[object Object]`.

The tool does not split nested data into related tables, and that is deliberate. Deciding that an array of objects should become a second table with a foreign key is schema design — it depends on how you intend to query the data, which the JSON does not say. A converter that guessed would be wrong often enough to be worse than useless.

If you want the nesting flattened into columns instead, run the JSON through a flattener first and convert the result.

## Common Mistakes

### Mistake 1: Trusting the CSV Round Trip

Covered above, and worth repeating because it fails silently. Check the type line.

### Mistake 2: Expecting Keys, Indexes or Constraints

The `CREATE TABLE` names columns and types and nothing else. A primary key depends on which field is actually unique, which the JSON does not state.

### Mistake 3: Assuming the First Row Sets the Schema

It does not. Every row is read before the types are fixed, which is why a decimal in row 900 still widens the column.

### Mistake 4: Running One Enormous Statement

Turn on multi-row INSERTs for a large array. They are chunked at 500 rows so no single statement becomes unmanageable.

### Mistake 5: Pasting an Array of Non-Objects

`[1, 2, 3]` has no keys, so it has no columns. The tool says so rather than inventing a column name.

## Review the Generated Schema

The generated SQL gives you a useful starting table. It cannot choose rules that do not exist in the JSON.

Check these items before you run the statements:

1. Confirm that the table name matches your target schema.
2. Review each inferred column type.
3. Decide whether a text column contains nested JSON.
4. Add a primary key only after you confirm uniqueness.
5. Add `NOT NULL` only after you inspect missing keys and null values.
6. Add indexes for the queries that your application will run.

Run a small sample first when the destination already contains data. A database error is easier to correct before a large import starts.

## Tools Used in This Guide

- [JSON to SQL](/convert/json-to-sql/) — this tool.
- [CSV to SQL](/convert/csv-to-sql/) — the same emitter, starting from a spreadsheet.
- [SQL to CSV](/convert/sql-to-csv/) — read rows back out of a dump.
- [JSON to CSV](/convert/json-to-csv/) — when a flat table really is what you want.
- [SQL Formatter](/developers/sql-formatter/) — pretty-print the result.

## FAQ

**Is my JSON uploaded?**
No. Parsing and generation both happen in your browser.

**How are types decided?**
From the real JSON values across every row. Nulls and missing keys are ignored while deciding.

**What happens to a nested object?**
It is stored as JSON text in one column, never `[object Object]`.

**Can I paste a single object?**
Yes, and NDJSON works too.

**Which dialects are supported?**
PostgreSQL, MySQL and SQLite.

**Does it create indexes or foreign keys?**
No. Those depend on how you query the data, which the JSON does not describe.

## Next Steps

Once the table exists, [SQL to CSV](/convert/sql-to-csv/) reads the rows back out of any dump you take of it, and [SQL Formatter](/developers/sql-formatter/) makes a long INSERT block readable in a pull request.
