Skip to main content
Version: 5.4

JSON Schema Matchers

MatcherDescriptionTargets
shouldMatchSchemaValidates that a String or kotlinx.serialization.JsonElement matches a JsonSchema. See description below for details on constructing schemas.Multiplatform

Parsing Schema

A subset of JSON Schemas can be defined either by parsing a textual schema. Example:

val parsedSchema = parseSchema(
"""
{
"$id": "https://example.com/geographical-location.schema.json", // will be ignored
"$schema": "https://json-schema.org/draft/2020-12/schema", // will be ignored
"title": "Longitude and Latitude Values", // will be ignored
"description": "A geographical coordinate.", // will be ignored
"required": [ "latitude", "longitude" ],
"type": "object",
"properties": {
"latitude": {
"type": "number",
"minimum": -90,
"maximum": 90
},
"longitude": {
"type": "number",
"minimum": -180,
"maximum": 180
}
}
}
"""
)

or using Kotest's built-in DSL:

val addressSchema = jsonSchema {
obj { // object is reserved, obj was chosen over jsonObject for brevity but could be changed ofc, or jsonObject could be added as alternative.
withProperty("street", required = true) { string() }
withProperty("zipCode", required = true) {
integer {
beEven() and beInRange(10000..99999) // supports constructing a matcher that will be used to test values
}
}
additionalProperties = false // triggers failure if other properties are defined in actual
}
}

val personSchema = jsonSchema {
obj {
withProperty("name", required = true) { string() }
withProperty("address") { addressSchema() } // Schemas can re-use other schemas 🎉
}
}

Building Schema

Array

Arrays are used for ordered elements. In JSON, each element in an array may be of a different type.

Length (minItems and maxItems)

The length of the array can be specified using the minItems and maxItems keywords. The value of each keyword must be a non-negative number and defaults are 0 and Int.MAX_VALUE

val lengthBoundedSchema = jsonSchema {
array(minItems = 0, maxItems = 1) { number() }
}

Uniqueness

A schema can ensure that each of the items in an array is unique. Simply set the uniqueItems keyword to true.

val uniqueArray = jsonSchema {
array(uniqueItems = true) { number() }
}

⚠️ Note that Kotest only supports a subset of JSON schema currently. Currently, missing support for:

  • $defs and $refs
  • Recursive schemas
  • Parsing of schema composition
  • string.format
  • array.prefixItems,
  • array.contains,
  • array.items = false
  • array.maxContains
  • array.minContains
  • array.uniqueItems
  • enum

Validating

Once a schema has been defined, you can validate String and kotlinx.serialization.JsonElement against it:

"{}" shouldMatchSchema personSchema

// fails with:
// $.name => Expected string, but was undefined

""" { "name": "Emil", "age": 34 } """
// Passes, since address isn't required and `additionalProperties` are allowed