100% local — your data never leaves your browser

JSON to Prisma — A Model That Migrates

Turn a JSON sample into a Prisma model. The identifier every model needs is always there, so prisma validate passes and the migration runs.

Instant Private Zero cookies

JSON input

Prisma output

What this tool does

A JSON sample becomes a Prisma model.

{ "id": 1, "name": "Ada", "tags": ["admin"], "score": 9.5 }
model Root {
  id    Int      @id
  name  String
  tags  String[]
  score Float
}

The model alone is not a schema.prisma: a working file also needs a datasource and a generator block. Those describe your database and your client, neither of which a payload mentions.

Every model gets an identifier

Prisma refuses a model without @id (or @@id) — prisma validate stops there. So:

  • an id that is an Int or a String becomes the identifier;
  • no id at all gets one added: id Int @id @default(autoincrement());
  • an id of some other type — a float, a boolean, a nested object — is renamed and keeps its original key:
model Root {
  id   Int    @id @default(autoincrement())
  id2  Float  @map("id")
  name String
}

That last case used to produce a model with no identifier at all: valid-looking Prisma that the CLI rejects. It was found while writing this page and fixed.

Nothing that looks like a relation is invented

A nested object becomes a Json column. It could have been a relation to another table, and guessing would mean inventing a model, a foreign key and a direction from one document. Same for an array of objects, and for a heterogeneous array.

A homogeneous list of scalars does get a native list — String[], Int[] — which exists on PostgreSQL, CockroachDB and MongoDB. On MySQL or SQLite, change it to Json: the output has no datasource, so it cannot know which you use.

Names, nullability, and what a sample does not say

Field names are camelCased, and @map keeps the original key whenever the two differ — so content-type becomes contentType @map("content-type") and your column name is unchanged. Two keys that camelCase to the same name are suffixed rather than merged.

Only null produces an optional column, Json?. Everything else is required, because the sample had a value — and a sample is the wrong place to learn that a column is nullable. The ? is one character, and yours to add.

Private by design

Everything runs locally in your browser with JavaScript. Your data is never uploaded, which makes the tool safe for sensitive content, and it keeps working offline.

Frequently asked questions

Where does the `id Int @id @default(autoincrement())` come from?
From Prisma\u2019s rule that every model needs an identifier. If your sample has an `id` that is an integer or a string, it becomes the identifier. Otherwise one is added, and any `id` of another type is renamed with `@map("id")` so the original key survives. Without it the model looked fine and `prisma validate` refused it.
Why is my nested object a `Json` column rather than a relation?
Because a sample cannot show a relation. `{"author": {"name": "Ada"}}` might be a foreign key to an `Author` table, or a blob that belongs in the row. Inventing the table, the key and the direction would be three guesses. `Json` keeps the data and leaves the modelling to you, where it belongs.
`String[]` does not compile on MySQL. Why is it there?
Because a homogeneous list of scalars has a native type in PostgreSQL, CockroachDB and MongoDB, and Prisma writes it `String[]`. MySQL and SQLite have no scalar lists: on those, change the field to `Json`. The generator cannot know your datasource — there is no datasource block in the output at all.

Related converters