JSON support JSON is a common format to interact between machines, as matter of fact, Kest comes with advanced support to that format with a bunch of assertions. It also comes with two Objects: JsonMap and JsonArray JsonMap is a Map<String, Any?> JsonArray is an array of JsonMap Matchers Kest provides several function to check whether a json content matches a Json pattern. To do so, Kest provides by default 3 matchers: {{string}} {{number}} {{boolean}} For example { "string": "a string", "number": 1, "boolean": true } is matched by { "string": "{{string}}", "number": "{{number}}", "boolean": "{{boolean}}" } or by { "string": "{{string}}", "number": 1, "boolean": "{{boolean}}" } And the function to check that with Kest would be: json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches validator { """ { "string": "{{string}}", "number": "{{number}}", "boolean": "{{boolean}}" } """ } // OR shortcuts are provided two write it without having to remember the notation json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches validator { """ { "string": "$stringPattern", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } Defining your own matchers If you want to define your own matchers, several possibilities: Define it textually val samplePattern = pattern("sample") definedBy """{ "string": "$stringPattern", "number": "$numberPattern", "boolean": "$booleanPattern" }""" To check match you can now call this: json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches validator { """ {{sample}} """ } // OR json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches samplePattern Define a class data class Sample( val string: String, val number: Int, val boolean: Boolean ) Then declare it as a pattern: val samplePattern = pattern("sample") definedBy Sample::class To check match you can now call this: json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches validator { """ {{sample}} """ } // OR json( """ { "string": "a string", "number": 1, "boolean": true }""" ) matches samplePattern Define a function that will check the validity of pattern fun checkDateFormat(data: String): Boolean { val dateFormatter = DateTimeFormatter.ofPattern("YYYY-MM-dd").withResolverStyle(STRICT) return try { dateFormatter.parse(data) true } catch (e: DateTimeParseException) { false } } Then declare it as a pattern: val samplePattern = pattern("sample") definedBy ::checkDateFormat To check match you can now call this: json( """ { "date": "2021-01-12", "number": 1, "boolean": true }""" ) matches validator { """ { "date": "{{sample}}", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } // OR json( """ { "date": "2021-01-12", "number": 1, "boolean": true }""" ) matches validator { """ { "date": "$samplePattern", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } Lists and nullable matchers Lists What if you want to check that an array contains a list of objects validating a pattern? { "data": [ { "string": "a string", "number": 1, "boolean": true }, { "string": "another string", "number": 2, "boolean": false } ] } val samplePattern = pattern("sample") definedBy """{ "string": "$stringPattern", "number": "$numberPattern", "boolean": "$booleanPattern" }""" To check match you can now call this: json( """ { "data": [ { "string": "a string", "number": 1, "boolean": true }, { "string": "another string", "number": 2, "boolean": false } ] }""" ) matches validator { """ { "data": "[[{{sample}}]]" } """ } // OR json( """ { "data": [ { "string": "a string", "number": 1, "boolean": true }, { "string": "another string", "number": 2, "boolean": false } ] }""" ) matches validator { """ { "data": "${jsonArrayOf(samplePattern)}", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } Nullable values val samplePattern = pattern("sample") definedBy """{ "string": "${stringPattern.nullable}", "number": "$numberPattern", "boolean": "$booleanPattern" }""" To check match you can now call this: json( """ { "string": null, "number": 1, "boolean": true }""" ) matches validator { """ { "string": "{{string?}}", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } // OR json( """ { "string": null, "number": 1, "boolean": true }""" ) matches validator { """ { "string": "${stringPattern.nullable}", "number": "$numberPattern", "boolean": "$booleanPattern" } """ } Polymorphism To go through polyphormism, Kest allows you to define a list of matchers for a given JSON. Let’s take this example: { "common": "{{string}}", "poly1": "{{string}}" } { "common": "{{string}}", "poly2": "{{string}}" } You can check whether your json matches one or the other of those matchers by passing a list to validator this way: json( """{ "common": "a string", "poly2": "another string" } """ ) matches validator( listOf( """{ "common": "{{string}}", "poly1": "{{string}}" } """, """{ "common": "{{string}}", "poly2": "{{string}}" } """ ) ) Lists It works all the same for lists! Tips For reading data easily from a JsonMap you may use function JsonMap.getForPath(…) For exemple for a JsonMap representing that Json: { "star": "wars", "characters": [ { "luke": "skywalker" }, { "han": "solo" }, { "R2": "D2" } ] } You may use it like that: val jsonMap: JsonMap val name1 = jsonMap.getForPath<String>("characters[0]", "luke") // == "skywalker" val name2 = jsonMap.getForPath<String>("characters[1]", "han") // == "solo" val name3 = jsonMap.getForPath<String>("characters[2]", "R2") // == "D2" Create a custom step Gherkin support