
Generates JSON schemas from annotated classes, supporting primitives, arrays, maps, nested objects, and enums. Ensures type-safety with KDoc subset and handles nullable fields. Experimental API.
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"]
}The current API is experimental and might change.
Add koja and the serialization plugin to your plugins block:
plugins {
kotlin("multiplatform") version "2.3.10" // or kotlin("jvm")
kotlin("plugin.serialization") version "2.3.10"
id("sh.ondr.koja") version "0.4.8"
}Koja includes a compiler plugin that requires exact Kotlin version matching:
| Koja Version | Required Kotlin Version |
|---|---|
| 0.4.8 | 2.3.10 |
| 0.4.7 | 2.3.0 |
| 0.4.6 | 2.2.21 |
| 0.4.4-0.4.5 | 2.2.20 |
| 0.4.3 | 2.2.10 |
| 0.4.1-0.4.2 | 2.2.0 |
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.
Issues and pull requests are welcome.
Licensed under the Apache License 2.0.
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"]
}The current API is experimental and might change.
Add koja and the serialization plugin to your plugins block:
plugins {
kotlin("multiplatform") version "2.3.10" // or kotlin("jvm")
kotlin("plugin.serialization") version "2.3.10"
id("sh.ondr.koja") version "0.4.8"
}Koja includes a compiler plugin that requires exact Kotlin version matching:
| Koja Version | Required Kotlin Version |
|---|---|
| 0.4.8 | 2.3.10 |
| 0.4.7 | 2.3.0 |
| 0.4.6 | 2.2.21 |
| 0.4.4-0.4.5 | 2.2.20 |
| 0.4.3 | 2.2.10 |
| 0.4.1-0.4.2 | 2.2.0 |
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.
Issues and pull requests are welcome.
Licensed under the Apache License 2.0.