Prisma Dmmf TransformerConceptsJSON Schema Generation

JSON Schema Generation

Last updated:

JSON Schema Generation

Understanding how Prisma models are transformed to JSON Schema v7.

JSON Schema v7

The transformer generates JSON Schema Draft 7 compliant schemas:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "definitions": {},
  "properties": {}
}

Model to Schema Mapping

Prisma models become JSON Schema definitions:

Input (Prisma)

model User {
  id    Int     @id @default(autoincrement())
  email String  @unique
  name  String?
  age   Int
}

Output (JSON Schema)

{
  "definitions": {
    "User": {
      "type": "object",
      "properties": {
        "id": {
          "type": "integer"
        },
        "email": {
          "type": "string"
        },
        "name": {
          "type": ["string", "null"]
        },
        "age": {
          "type": "integer"
        }
      }
    }
  },
  "properties": {
    "user": {
      "$ref": "#/definitions/User"
    }
  }
}

Type Conversion

Scalar Types

Prisma types convert to JSON Schema types:

Prisma TypeJSON Schema Type
String"string"
Int"integer"
BigInt"integer"
Float"number"
Decimal"number"
Boolean"boolean"
DateTime"string" with format: "date-time"
Json"object"
Bytes"string"

Optional Fields

Optional Prisma fields use null union types:

model User {
  name String?  // Optional
}
{
  "name": {
    "type": ["string", "null"]
  }
}

Arrays

List fields use JSON Schema arrays:

model User {
  tags String[]
}
{
  "tags": {
    "type": "array",
    "items": {
      "type": "string"
    }
  }
}

Enums

Prisma enums become JSON Schema enums:

enum Role {
  USER
  ADMIN
  MODERATOR
}

model User {
  role Role @default(USER)
}
{
  "definitions": {
    "Role": {
      "type": "string",
      "enum": ["USER", "ADMIN", "MODERATOR"]
    },
    "User": {
      "type": "object",
      "properties": {
        "role": {
          "$ref": "#/definitions/Role"
        }
      }
    }
  }
}

Relations

Relation handling depends on keepRelationScalarFields option:

With keepRelationScalarFields: "false"

Relations use object references:

model Post {
  author   User @relation(fields: [authorId], references: [id])
  authorId Int
}
{
  "properties": {
    "author": {
      "$ref": "#/definitions/User"
    }
  }
}

Foreign key (authorId) is omitted.

With keepRelationScalarFields: "true"

Both relation and foreign key are included:

{
  "properties": {
    "author": {
      "$ref": "#/definitions/User"
    },
    "authorId": {
      "type": "integer"
    }
  }
}

Required Fields

With includeRequiredFields: "true", the schema includes required field constraints:

model User {
  id    Int    @id
  email String
  name  String?
}
{
  "type": "object",
  "properties": {
    "id": { "type": "integer" },
    "email": { "type": "string" },
    "name": { "type": ["string", "null"] }
  },
  "required": ["id", "email"]
}

Original Type Information

With persistOriginalType: "true", Prisma types are preserved:

{
  "email": {
    "type": "string",
    "prismaType": "String"
  },
  "createdAt": {
    "type": "string",
    "format": "date-time",
    "prismaType": "DateTime"
  }
}

Useful for generators that need Prisma-specific information.

Schema ID

The schemaId option sets the $id property:

transformDMMF(dmmf, {
  schemaId: "https://api.example.com/schema",
});
{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "https://api.example.com/schema",
  "type": "object",
  "definitions": {}
}

This creates resolvable references:

{
  "$ref": "https://api.example.com/schema#/definitions/User"
}

Definitions vs Properties

The schema has two main sections:

Definitions

Reusable model schemas:

{
  "definitions": {
    "User": { /* schema */ },
    "Post": { /* schema */ }
  }
}

Properties

Top-level references (camelCase model names):

{
  "properties": {
    "user": { "$ref": "#/definitions/User" },
    "post": { "$ref": "#/definitions/Post" }
  }
}

Composite Types

Prisma composite types (MongoDB) are transformed similarly:

type Address {
  street String
  city   String
  zip    String
}

model User {
  address Address
}
{
  "definitions": {
    "Address": {
      "type": "object",
      "properties": {
        "street": { "type": "string" },
        "city": { "type": "string" },
        "zip": { "type": "string" }
      }
    },
    "User": {
      "type": "object",
      "properties": {
        "address": {
          "$ref": "#/definitions/Address"
        }
      }
    }
  }
}
Support

Contribute to our work and keep us going

Community is the heart of open source. The success of our packages wouldn't be possible without the incredible contributions of users, testers, and developers who collaborate with us every day.Want to get involved? Here are some tips on how you can make a meaningful impact on our open source projects.

Ready to help us out?

Be sure to check out the package's contribution guidelines first. They'll walk you through the process on how to properly submit an issue or pull request to our repositories.

Submit a pull request

Found something to improve? Fork the repo, make your changes, and open a PR. We review every contribution and provide feedback to help you get merged.

Good first issues

Simple issues suited for people new to open source development, and often a good place to start working on a package.
View good first issues