Understanding JSON → Prisma
A schema, not just a type.
Why generating a Prisma model from a JSON sample is a different problem from generating a TypeScript type, and which of the two you actually want.
Prisma models are database schemas.
A Prisma model in schema.prisma is the source of truth for a database table — columns, types, constraints, relations, indexes. Generating one from a JSON sample tells you what the storage layer should look like, not what the in-memory shape is. The two are almost always related but rarely identical: the JSON has nested objects that translate into separate tables with foreign keys, arrays that become join tables, dates that become DateTime columns with timezone decisions.
The shape Prisma emits.
A model declares a name, a body of fields, and zero or more attributes per field. Fields have a name, a type (String, Int, DateTime,Boolean, Json, or a relation), and modifiers (? for optional, [] for arrays, @id for primary key, @default for defaults, @unique for unique indexes, @relation for foreign keys).
A worked example.
From { "id": 7, "email": "a@b.com", "name": "Q", "createdAt": "2026-05-13T12:00:00Z" }: model User {
id Int @id @default(autoincrement())
email String @unique
name String
createdAt DateTime @default(now())
} The id became an integer primary key with auto-increment. The email got @unique because that's the convention for that name. createdAt got a server-side now() default. Codegen inferrers detect these conventions; ones that don't produce a schema you'll spend an hour fixing.
Conventional inferences
id → @id, email → @unique, createdAt → @default(now())
Naming conventions trigger schema attributes.
JSON sample → Prisma model body + attributes
= Migration-ready schema
Relations are the hard part.
A nested JSON object — "author": { "id": 1, "name": "Q" } — could be a one-to-one relation, a one-to-many parent, a denormalised copy, or a JSON column. Inferrers can't know which. Most default to "create a separate model and a relation" which is right for entities that get queried independently and wrong for value-objects that only ever appear nested. Review the inferred relations; flip them to Json columns where appropriate.
Indexes don't come free.
A naive schema generator emits one index — the primary key. Real databases need more: @@index([userId, createdAt]) for the common access pattern, @unique on natural keys, partial indexes for nullable filters. The inferrer can't see your query patterns; you'll add these as the schema matures. The mistake is treating the generated schema as final.
Migrations are downstream.
The Prisma model is the input to prisma migrate dev, which generates SQL migrations and applies them. Generating a model from JSON is therefore the start of a workflow, not the end. Run the model through migrate; check the SQL it produces; commit both the schema and the migration. The same JSON-to-model output is legitimate for a fresh database and dangerous for a database with existing data — migrations need to preserve what's already there.