Annotate classes with @JsonSchema
and @Serializable
.
Then call jsonSchema<YourClass>()
:
/**
* A person with a name, age, and email addresses.
* @param name The person's name.
* @param age The person's age.
* @param emails The person's email addresses.
*/
@Serializable @JsonSchema
data class PersonWithMail(
val name: String,
val age: Int?,
val emails: List<String> = emptyList(),
)
@KojaEntry
fun main() {
val schema = jsonSchema<PersonWithMail>()
println(schema.toJsonElement())
}
Output:
{
"type": "object",
"description": "A person with a name, age, and email addresses.",
"properties": {
"name": {
"type": "string",
"description": "The person's name."
},
"age": {
"type": "number",
"description": "The person's age."
},
"emails": {
"type": "array",
"description": "The person's email addresses.",
"items": {
"type": "string"
}
}
},
"required": ["name"]
}
- Handles primitives, arrays, maps, nested objects, and enums
- Supports nullable fields and defaults
- Works on multiple platforms (JVM, JS, Native, iOS, Android)
- Uses stricter KDoc subset for improved type-safety (throws compile error when specifying non-existing properties)
The current API is experimental and might change.
Add koja and the serialization plugin to your plugins block:
plugins {
kotlin("multiplatform") version "2.1.0" // or kotlin("jvm")
kotlin("plugin.serialization") version "2.1.0"
id("sh.ondr.koja") version "0.3.2"
}
Koja was primarily written for mcp4k.
If used as a standalone library, you have to mark the application entry point to manually push the collected KDocs into the registry:
@KojaEntry
fun main() {
// your code here
}
@JsonSchema @Serializable
data class Address(
val city: String,
val zip: Int,
)
@JsonSchema @Serializable
data class Company(
val name: String,
val employees: Map<String, Int>,
val headquarters: Address,
)
val companySchema = jsonSchema<Company>()
println(companySchema.toJsonElement())
Output:
{
"type": "object",
"properties": {
"name": { "type": "string" },
"employees": {
"type": "object",
"additionalProperties": { "type": "number" }
},
"headquarters": {
"type": "object",
"properties": {
"city": { "type": "string" },
"zip": { "type": "number" }
},
"required": ["city", "zip"]
}
},
"required": ["name", "employees", "headquarters"]
}
Enums become string
schemas with enum
arrays.
- ✅ Validate map key types
- ✅ Property descriptions (KDocs)
- ⬜ References
- ⬜ Fine-grained number types (integers vs numbers)
- ⬜ Advanced validation keywords (e.g. patterns)
- ⬜ Configurable handling of nullable types
- ⬜ Property descriptions (Annotations)
Issues and pull requests are welcome.
Licensed under the Apache License 2.0.