Skip to content

ashtrindade/kassandra

Repository files navigation

Kassandra

JSON validation library with kotlinx.serialization.

Installation

Check the latest version in Releases.

Versions catalog

[versions]
kassandra = "<last-version>"

[libraries]
kassandra = { module = "io.github.ashtrindade:kassandra", version.ref = "kassandra" }
dependencies {
    implementation(libs.kassandra)
}

Maven

<!-- https://mvnrepository.com/artifact/io.github.ashtrindade/kassandra -->
<dependency>
    <groupId>io.github.ashtrindade</groupId>
    <artifactId>kassandra</artifactId>
    <version>last-version</version>
    <scope>runtime</scope>
</dependency>

Gradle

Kotlin

implementation("io.github.ashtrindade:kassandra:<last-version>")

Goovy

implementation 'io.github.ashtrindade:kassandra:<last-version>'

Usage

JSON Schema

Validates a JSON object against the schema provided at construction.

  • Params:
    • schema - The schema to compare against.
    • json - The JSON object to validate.
  • Returns:
    • ValidationResult.Success if valid, or ValidationResult.Failure with error messages.
val input = """{"name": "Ash", "age": 30, "role": "admin"}"""
val schema = """
    {
      "type": "object",
      "required": ["name", "age"],
      "properties": {
        "name": { "type": "string", "minLength": 1 },
        "age": { "type": "integer", "minimum": 0 },
        "role": { "type": "string", "enum": ["user", "admin"] }
      }
    }
    """

val inputJson = Json.parseToJsonElement(input)
val schemaJson = Json.parseToJsonElement(schema)

val result = Validator.validate(schemaJson.jsonObject, inputJson.jsonObject)

Serializable Data Class with JSON string or object

Validates a JSON string against the serializer provided at construction. Your data class must be Serializable and have an init body with the validations.

@Serializable
class Project(val name: String) {
    init {
        require(name.isNotEmpty()) { "name cannot be empty" }
    }
}

fun main() {
    val data = Json.parseToJsonElement("{\"name\":\"Hellen\"}").jsonObject
    println(data)
}

If any part of the validation fails produces the exception:

Exception in thread "main" java.lang.IllegalArgumentException: name cannot be empty
  • Params:
    • model - Data class to compare against.
    • json - The JSON string or object to validate.
  • Returns:
    • ValidationResult.Success with model if valid, or ValidationResult.Error with error message.

DSL schema

Builds a custom validator using jackson or kotlinx.serialization.

val validator = jsonValidator {
  // Ensure "name" exists and is a non-empty string
  field("name") {
    exists()
    isString()
    length(min = 1)
  }

  // Ensure "age" exists, is integer, and is >= 0
  field("age") {
    exists()
    isInt()
    range(min = 0, max = 150)
  }

  // Cross-field rule: if "role" == "admin", "accessKey" must be present
  rule("adminAccessKey") { node ->
    if (node.path("role").asText() == "admin" && node.path("accessKey").isMissingNode) {
      ValidationResult.Failure(listOf("accessKey is required for admin"))
    } else {
      ValidationResult.Success
    }
  }
}

fun main() {
  val json = """{"name": "Ash", "age": 30, "role": "admin"}"""

  // with jackson
  val mapper = ObjectMapper()
  val node: JsonNode = mapper.readTree(json)

  // with kotlinx.serialization
  val node = Json.decodeFromString<T>(json) // T is you serializable data class.
  
  // if you just want parse to json without a data class do this:
  val node = Json.parseToJsonElement(json).jsonObject

  when (val result = validator.validate(node)) {
    is ValidationResult.Success -> println("All good!")
    is ValidationResult.Failure -> println("Errors: ${result.errors}")
  }
}

About

JSON validation library with kotlinx.serialization.

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages