SQL·Kotlin·Free

SQL to
Kotlin.

Turn a CREATE TABLE script into Kotlin data class models. One file per table, camelCase field names, nullable columns as Type? = null, and SQL enum types as @Serializable enum class. No ORM wiring, no annotations you did not ask for.

DDL·Kotlin·JVM·Package·MIT
payments.sqlInput
CREATE TYPE payment_method AS ENUM ('card', 'bank', 'wallet');

CREATE TABLE payments (
    id UUID PRIMARY KEY,
    amount DECIMAL(12, 2) NOT NULL,
    currency VARCHAR(3),
    method payment_method NOT NULL,
    created_at TIMESTAMP NOT NULL
);
compile
Payments.kt tsc cleanOutput
// Payments.kt
package com.example.payments

import kotlinx.serialization.Serializable

import java.util.UUID
import java.math.BigDecimal
import java.time.LocalDateTime
import kotlinx.serialization.Contextual

@Serializable
data class Payments(
    val id: @Contextual UUID,
    val amount: @Contextual BigDecimal,
    val currency: String? = null,
    val method: PaymentMethod,
    val createdAt: @Contextual LocalDateTime
)
What gets generated

Kotlin data classes. Nothing more.

Below: a small payments schema with an enum type, rendered to Kotlin. Each table becomes a @Serializable data class; each SQL ENUM becomes a @Serializable enum class. The output is model types — no table mapper, no query DSL, no entity manager.

// PaymentMethod.kt — enum type, one file
package com.example.payments

import kotlinx.serialization.Serializable
import kotlinx.serialization.SerialName

@Serializable
enum class PaymentMethod {
    @SerialName("card")
    CARD,
    @SerialName("bank")
    BANK,
    @SerialName("wallet")
    WALLET
}

// Payments.kt — table, one file
package com.example.payments

import kotlinx.serialization.Serializable

import java.util.UUID
import java.math.BigDecimal
import java.time.LocalDateTime
import kotlinx.serialization.Contextual

@Serializable
data class Payments(
    val id: @Contextual UUID,
    val amount: @Contextual BigDecimal,
    val currency: String? = null,
    val method: PaymentMethod,
    val createdAt: @Contextual LocalDateTime
)
Three things we get right

Grounded in how the DDL reads.

Each claim here is something you can verify by pasting your own schema into the converter. Click a card to see the DDL fragment that triggered it and the Kotlin that came out.

01Proofsnake_case columns become camelCase fields.Spec · InCode · Out
schema.sql fragment
CREATE TABLE employees (
    id INT PRIMARY KEY,
    first_name VARCHAR(50) NOT NULL,
    last_name VARCHAR(50) NOT NULL,
    email VARCHAR(150) UNIQUE NOT NULL,
    hire_date DATE NOT NULL,
    salary DECIMAL(10, 2),
    department_id INT NOT NULL
);
emitted Employees.kt
// Employees.kt
package com.example.models

import kotlinx.serialization.Serializable

import java.time.LocalDate
import java.math.BigDecimal
import kotlinx.serialization.Contextual

@Serializable
data class Employees(
    val id: Int,
    val firstName: String,
    val lastName: String,
    val email: String,
    val hireDate: LocalDate,
    val salary: @Contextual BigDecimal? = null,
    val departmentId: Int
)
Plain Kotlin

Data classes, ready to drop in.

One Kotlin data class per CREATE TABLE, inside a package you choose. No JPA annotations, no Exposed tables, no runtime you did not already have. The types are annotated for kotlinx.serialization; wire them to whatever DB layer your project already uses.

src/main/kotlin/com/example/models/ generated
// Departments.kt
package com.example.models

import kotlinx.serialization.Serializable

@Serializable
data class Departments(val id: Int, val name: String, val location: String? = null)

// Employees.kt
package com.example.models

import kotlinx.serialization.Serializable

import java.time.LocalDate
import java.math.BigDecimal
import kotlinx.serialization.Contextual

@Serializable
data class Employees(
    val id: Int,
    val firstName: String,
    val lastName: String,
    val email: String,
    val hireDate: LocalDate,
    val salary: @Contextual BigDecimal? = null,
    val departmentId: Int
)
Also available via MCP

Or ask Claude to do it.

The same generator ships as a Model Context Protocol server. It calls the same web API this converter uses, so the output is identical. Point Claude Desktop, Cursor, or any MCP-aware agent at a <code>.sql</code> file and it produces the Kotlin models as a diff — free, no token, no leaving the chat.

// claude-desktop config · .mcp.json
{
  "mcpServers": {
    "metaengine": {
      "command": "npx",
      "args": ["-y", "@metaengine/mcp-server"]
    }
  }
}

// Then in Claude:
// "Load db/schema.sql and generate Kotlin
//  models in package com.acme.domain."
See the MCP page
Questions

Things people ask.

The niche between "hand-writing model classes" and "pulling in an ORM" is thinly covered. Most of these answer what you actually get.

One Kotlin file per CREATE TABLE and one per CREATE TYPE ... AS ENUM, under a package you provide. The output is model types only — no query DSL, no table mappers, no repository layer. You get the data classes; you pick the data layer.
More converters

Same engine, other stacks.

Every converter runs the same spec-to-IR pipeline. Pick another source format or target stack.

OpenAPITypeScript
Angular httpResource, React TanStack Query, or framework-agnostic fetch.
Open converter
OpenAPIAngular
Typed services with httpResource, Signals, inject() DI, and interceptors.
Open converter
OpenAPIReact
TanStack Query hooks with stable query keys, or plain async functions.
Open converter
OpenAPIFetch
Framework-agnostic fetch client with ApiResult, middleware, and retries.
Open converter
OpenAPIJava Spring
RestClient services, Java records, sealed interfaces, Spring Boot 3.
Open converter
OpenAPIPython
Async httpx clients paired with Pydantic v2 models.
Open converter
OpenAPIGo
Idiomatic net/http client, context-aware, pointer-nullable fields.
Open converter
OpenAPIKotlin
Ktor client, kotlinx.serialization, sealed interfaces for oneOf.
Open converter
OpenAPIC#
Records, nullable reference types, JsonPolymorphic, HttpClient.
Open converter
OpenAPIRust
reqwest client with serde-tagged enums for oneOf and Option<T>.
Open converter
GraphQLAngular
Observable services with typed queries, mutations, and graphql-ws subscriptions.
Open converter
GraphQLReact
TanStack Query hooks with discriminated-union types and query keys.
Open converter
GraphQLKotlin
Ktor, kotlinx.serialization, Flow-based subscriptions.
Open converter
GraphQLC#
Records, nullable types, [JsonPolymorphic] unions, IAsyncEnumerable subscriptions.
Open converter
ProtobufKotlin
Ktor, coroutines, and sealed classes straight from .proto.
Open converter
ProtobufC#
Records, nullable types, Connect RPC over HttpClient.
Open converter
ProtobufGo
Plain structs with json tags, pointer presence, stdlib-only Connect client.
Open converter
SQLTypeScript
Postgres DDL to typed interfaces with foreign-key navigation.
Open converter

Try it on your own schema.

The converter runs in the browser. Your DDL never leaves the page.

Open the converter