REST Assured Tutorial 55 – JSON Schema Validation in Rest Assured

Introduction

As a part of End to End REST Assured Tutorial, in this post, we will learn about JSON Schema validation in Rest Assured.

In most of the tutorials, JSON schema validation in Rest Assured is shown for JSON response only or professionals understand that JSON schema validation can be done only for a JSON response. That is not correct. Any JSON can be validated against a related JSON schema.

Prerequisite

I have used below dependency of Rest Assured library for this post:-



    io.rest-assured
    rest-assured
    4.3.1
    test

If you are not aware of JSON Schema, learn about that here.

Adding maven dependency of json-schema-validator

Rest Assured provides support to JSON schema validation since 2.1.0 version. But to use this feature we need to add another Java library “json-schema-validator” in our project classpath. Since I am using a maven project I will add the below dependency in pom.xml:-



    io.rest-assured
    json-schema-validator
    4.3.1

Be careful when you search the above dependency in Maven central repo as there are multiple libraries with the same name. Make sure you look groupId as “io.rest-assured“. You can also quickly find by seeing Rest Assured official logo. If you are using non-maven project then you can download JAR file and add to classpath.

You should also add the same version of json-schema-validator as of Rest assured (4.3.1 is this case).

Class JsonSchemaValidator

JsonSchemaValidator class provides multiple overloaded static methods to perform JSON schema validation.

public static JsonSchemaValidator matchesJsonSchemaInClasspath(String pathToSchemaInClasspath) – Creates a Hamcrest matcher that validates that a JSON document conforms to the JSON schema provided to this method.

public static JsonSchemaValidator matchesJsonSchema(File file) – Creates a Hamcrest matcher that validates that a JSON document conforms to the JSON schema provided to this method.

If you keep JSON Schema files in the resource folder of your project or src/test/resources of a maven project then you can use matchesJsonSchemaInClasspath() method directly as you just need to pass the name of the JSON schema file. If you store JSON schema files at different locations within the project or outside the project then you can use the overloaded method matchesJsonSchema().

Asserting JSON response against JSON Schema

Create JSON Schema

I will use the same JSON Schema shown in this post. This JSON schema is generated for Restful Booker – Auth API. Let’s save below JSON schema under src/test/resources folder.

AuthJsonSchema.json

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {},
    "examples": [
        {
            "token": "abc123"
        }
    ],
    "required": [
        "token"
    ],
    "properties": {
        "token": {
            "$id": "#/properties/token",
            "type": "string",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}

Performing JSON Schema validation using matchesJsonSchemaInClasspath()

We can directly call schema validator methods in an overloaded body(Matcher matcher) method. You may be thinking the return type of JSON Schema validator methods is JsonSchemaValidator so how can we pass them to body(Matcher matcher) method. This is because of multilevel inheritance. Class JsonSchemaValidator implements Interface Matcher indirectly.

Program
package JsonSchema;

import org.hamcrest.Matchers;
import org.testng.annotations.Test;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.module.jsv.JsonSchemaValidator;

public class VerifyJsonSchema {

	@Test
	public void verifyJsonSchema() {
		
		String jsonStringPayload = "{\"username\" : \"admin\",\"password\" : \"password123\"}";

		// GIVEN
		RestAssured
			.given()
				.baseUri("https://restful-booker.herokuapp.com/auth")
				.contentType(ContentType.JSON)
				.body(jsonStringPayload)
		// WHEN
			.when()
				.post()
		// THEN
			.then()
				.assertThat()
				.statusCode(200)
				.body("token", Matchers.notNullValue())
				.body(JsonSchemaValidator.matchesJsonSchemaInClasspath("AuthJsonSchema.json"));
	}

}

The above test will pass. Let’s make some changes to the expected JSON schema to fail validation and understand the error messages.

Adding extra required properties

As of now, we get only one property “token” in response. Let’s add a new property under the “required” section of JSON schema.

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {},
    "examples": [
        {
            "token": "abc123"
        }
    ],
    "required": [
        "token",
        "nonExistingProperty"
    ],
    "properties": {
        "token": {
            "$id": "#/properties/token",
            "type": "string",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}

Run the above Rest Assured test and you will get console error as:-

You can see clearly that the log shows that a required field is missing.

Change the data type of properties

Property “key” holds a String value. Let’s change it to integer and observe the output.

{
    "$schema": "http://json-schema.org/draft-07/schema",
    "$id": "http://example.com/example.json",
    "type": "object",
    "title": "The root schema",
    "description": "The root schema comprises the entire JSON document.",
    "default": {},
    "examples": [
        {
            "token": "abc123"
        }
    ],
    "required": [
        "token"
    ],
    "properties": {
        "token": {
            "$id": "#/properties/token",
            "type": "integer",
            "title": "The token schema",
            "description": "An explanation about the purpose of this instance.",
            "default": "",
            "examples": [
                "abc123"
            ]
        }
    },
    "additionalProperties": true
}

Run the same Rest Assured test again and you will get the output as below:-

You can see that it validates that a string value is found instead of an integer.

Above are just some examples of validation types. We can do a lot using this feature.

Performing JSON Schema validation using matchesJsonSchema()

Above we kept JSON schema file within src/test/resources folder and used matchesJsonSchemaInClasspath() method. We can not use this method if we do not have JSON schema in the resource folder. You will get IllegalArgumentException stating Schema to use cannot be null.

Note – I have mentioned src/test/resources to keep schema files. In fact, you can keep them in src/main/resources folder as well. Your Test classes can also be in any src/main/java or src/test/java but tests should be kept under src/test/java as a standard practice. Make sure you remove <scope> tag from maven dependency in pom.xml .

In that case, we can use another overloaded static method matchesJsonSchema() where you can pass a complete path of JSON Schema.

package JsonSchema;

import java.io.File;

import org.hamcrest.Matchers;
import org.testng.annotations.Test;

import io.restassured.RestAssured;
import io.restassured.http.ContentType;
import io.restassured.module.jsv.JsonSchemaValidator;

public class VerifyJsonSchemaNonResource {

	@Test
	public void verifyJsonSchema() {
		
		String jsonStringPayload = "{\"username\" : \"admin\",\"password\" : \"password123\"}";

		// GIVEN
		RestAssured
			.given()
				.baseUri("https://restful-booker.herokuapp.com/auth")
				.contentType(ContentType.JSON)
				.body(jsonStringPayload)
		// WHEN
			.when()
				.post()
		// THEN
			.then()
				.assertThat()
				.statusCode(200)
				.body("token", Matchers.notNullValue())
				.body(JsonSchemaValidator.matchesJsonSchema(new File("C:\\Users\\amomahaj\\git\\master\\src\\test\\java\\JsonSchema\\schema.json")));
	}

}

Remember that you need to pass the file path using a File object. Do not directly give file path as String. The method matchesJsonSchema() expects JSON schema as a string not a file path as String.

Summary

  1. We need to add another Java library “json-schema-validator” in our project classpath to perform JSON schema validation.
  2. Class JsonSchemaValidator provides static overloaded methods matchesJsonSchema() and matchesJsonSchemaInClasspath() to validate JSON schema.
  3. If we keep the expected JSON schema JSON file in the resource section then use matchesJsonSchemaInClasspath() method. You can use matchesJsonSchema() method as well.
  4. If we do not keep the expected JSON schema JSON file in the resource section then use matchesJsonSchema() method.

You can download/clone the above sample project from here.

You can subscribe to my YouTube channel RetargetCommon to learn from video tutorials.

If you have any doubt, feel free to comment below.
If you like my posts, please like, comment, share and subscribe.
#ThanksForReading
#HappyLearning

Find all Selenium related posts here, all API manual and automation related posts here, and find frequently asked Java Programs here.

Many other topics you can navigate through the menu.

2 thoughts on “REST Assured Tutorial 55 – JSON Schema Validation in Rest Assured

  1. Amod
    facing issue
    java.lang.IllegalArgumentException: Schema to use cannot be null

    at io.restassured.module.jsv.JsonSchemaValidator.validateSchemaIsNotNull(JsonSchemaValidator.java:270)
    at io.restassured.module.jsv.JsonSchemaValidator.access$300(JsonSchemaValidator.java:75)
    at io.restassured.module.jsv.JsonSchemaValidator$JsonSchemaValidatorFactory.create(JsonSchemaValidator.java:281)
    at io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchema(JsonSchemaValidator.java:166)
    at io.restassured.module.jsv.JsonSchemaValidator.matchesJsonSchemaInClasspath(JsonSchemaValidator.java:117)
    at com.rest.JsonSchemaValidation.validateJsonSchema(JsonSchemaValidation.java:23)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:568)
    at org.testng.internal.invokers.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:139)
    at org.testng.internal.invokers.TestInvoker.invokeMethod(TestInvoker.java:677)
    at org.testng.internal.invokers.TestInvoker.invokeTestMethod(TestInvoker.java:221)
    at org.testng.internal.invokers.MethodRunner.runInSequence(MethodRunner.java:50)
    at org.testng.internal.invokers.TestInvoker$MethodInvocationAgent.invoke(TestInvoker.java:962)
    at org.testng.internal.invokers.TestInvoker.invokeTestMethods(TestInvoker.java:194)
    at org.testng.internal.invokers.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:148)
    at org.testng.internal.invokers.TestMethodWorker.run(TestMethodWorker.java:128)

  2. You’re a hero 🙂 You’ve simplified and made every aspect of automation so easy and understandable, thank you, keep up the good work

Leave a Reply

Your email address will not be published. Required fields are marked *