Extracting a JSON Response with Rest-Assured

In the previous blog post on Getting up and Running with Rest-Assured, we went over everything that we needed to get up and running quickly. In this post I am going to focus on one of the features of Rest-Assured that I use regularly: extracting a response .

REST Assured Fundamentals – Out now on Udemy!

Introduction

This post will cover REST Assured extract response from an API into a ‘Response‘ class. Once we have extracted the response, we can perform various tests to check the content of that response. I will also demonstrate how we can set the Base URI and the Base Path easily.

Please note that in all of my blog posts on REST Assured I am going to assume that you have a decent working knowledge of Java and Junit. If you have little or no experience with those, I can highly recommend the book from Alan Richardson called Java For Testers which will get you up to speed in no time!

Setting Base URL and Path

Let’s start with an example that shows how to set the base URI and base Path. In your project in your IDE go ahead and create a new test class. Add the following code:

It should be quite obvious what we are doing here. We are simply setting the default URI and default basePath to use in all of our tests.

Now when we write out a test that calls an API (as we will do in the next step), we don’t have to type in the full address of the API.

Extract a Response from the API

Moving on, let’s look at REST Assured extract response. Type out the following code so that your class looks like below, which will make a call to our API called ‘rides’:

public class RestAssuredTest {
public static Response response;
public static String jsonAsString;
@BeforeClass
public static void setupURL()
{
// here we setup the default URL and API base path to use throughout the tests
RestAssured.baseURI = "http://yourwebsiteaddress.com";
RestAssured.basePath = "/api/yourapi/";
}
@BeforeClass
public static void callRidesAPI()
{
// call the rides API, the full address is "http://yourwebsiteaddress.com/api/yourapi/rides",
// but we set the default above, so just need "/rides"
response =
when().
get("/rides").
then().
contentType(ContentType.JSON). // check that the content type return from the API is JSON
extract().response(); // extract the response
// We convert the JSON response to a string, and save it in a variable called 'jsonAsString'
jsonAsString = response.asString();
}
}

Let’s talk through the code and work out what’s going on. At the top of the test we set a couple of variables:

public static Response response;
public static String jsonAsString;

These will be used to hold our response from the API, and then to convert that response into a String.

So here we are using the traditional given / when / then structure that we outlined in the previous post, but we are skipping the ‘given’ part since we don’t have to specify any parameters for this call.

We start with the ‘when‘ method and use the ‘get’ method to call ‘/rides‘. Remember that we set the defaults for the base URI and Path at the start of the test, so the full address of the api that is actually being called here is ‘http://yourwebsiteaddress.com/api/yourapi/rides‘.

Next we move on to the ‘then‘ part to check the response. We simply add a check ‘contentType(ContentType.JSON)‘ to make sure that the response we get is in JSON format.

With all of the above completed we can now extract the response into the variable by calling the ‘extract().response()‘ methods.

Now that we have the response saved into a variable, it’s simply a case of converting that into a String:

jsonAsString = response.asString();

We now have a variable with the JSON response as a String, and we can use that for our subsequent testing.

Example JSON

The above API address is obviously not real and will not return any data. If you have access to an API that will return a JSON response then feel free to use that instead. I will be releasing a custom built API for both JSON and XML in my video tutorial series on REST Assured.

For demonstration purpose in the meantime, this is an example of the JSON that would be returned from making a call to this sort of API – some data on rides in a theme park:

Asserting on the Response

So now that we have the above JSON as a String in our test, we can use Rest-Assured to do some testing to check the response.

A simple test would be to check the number of rides that our returned by the API call, i.e. the number of entries in the JSON response.

One way we could do this is with an ArrayList. Type out the following test below (still inside the ‘RestAssuredTest.class’ file):

@Test
public void checkForNumberOfRides()
{
// first we put our 'jsonAsString' into an ArrayList of Maps of type <String, ?>
ArrayList<Map<String,?>> jsonAsArrayList = from(jsonAsString).get("");
// now we count the number of entries in the JSON file, each entry is 1 ride
assertThat(jsonAsArrayList.size(), equalTo(3));
}

In the above code, we use Rest-Assured to convert our ‘jsonAsString’ String into an ArrayList of Map<String,?> called ‘jsonAsArrayList’.

We then do an assertThat on the jsonAsArrayList to check that the size is equal to 3, the same as the number of entries in the JSON response.

Another test that we could perform is to check that the ‘state’ of all the rides is equal to open. This time we will just use the ‘response’ variable (not the string!) and we will convert that into a List<String>. Type out the following test:

@Test
public void checkAllRidesAreOpen()
{
// put all of the ride states into a list
List<String> rideStates = response.path("state");
// check that they are all 'open'
for (String rideState : rideStates)
{
assertThat(rideState, equalTo("open"));
}
}

In the above code we create a List of the rideStates by taking the response variable and calling the ‘.path‘ method with the argument (“state”).

What this REST Assured code simply does is goes through the JSON response and looks for all the ‘state’ keys and adds their value to a list. In this case, it should add three entries to the List that should all be “open”. Finally we use a foreach loop to check that all of the entries in the List are equal to “open”.

Summary

In this post we explored how we can extract a JSON response from an API directly into our code and then how we can execute tests to check that the content is as we expected. This is barely scratching the surface of what REST Assured can do, and there are literally hundreds of different tests that we could execute, but hopefully after reading this you are getting some idea of what can be done.

Unfortunately in this test we didn’t have access to an API that we could actually use and therefore we couldn’t actually see any of these tests running. In the next post, I will type the JSON example in this post directly into our program and then we can use that as if we had called the API and converted it into a String (as we did in this post). Continuing with the ‘Rides’ theme, I am also going to demonstrate how you can write some test data into your program, add that to a Java Map, and then compare your test data with the response from the URL. We will also be executing some parameterised testing using the JUnitParams library.

Hi James
Thank you for the detailed tutorial on Rest Assured. I tried to copy your code and run it on my eclipse. I have included rest-assured-1.6.jar and hamcrest.jar. I have used the following import statements :
import static org.hamcrest.Matchers.*;
import static com.jayway.restassured.matcher.RestAssuredMatchers.*;
import static com.jayway.restassured.RestAssured.*;
import static com.jayway.restassured.http.ContentType.JSON;
import static com.jayway.restassured.RestAssured.get;

But my eclipse does not recognize the when()and then() methods. Can you please let me know if there are any other import statements that I should include.
Thanks.

Bogdan

Try to import also:

import com.jayway.restassured.specification.ResponseSpecification;

Vimal

Hi ,

Thank you for the detailed tutorial on Rest Assured,my eclipse does not recognize the “from” Method for Array List. What I need to import? Thanks

http://www.fluentwait.com Fluent Wait

Hi,

Please check out my video which is done in Intellij for rest assured implementation.

Bindu

Hi James,

I tried using response.asString(); to convert the response into a string. But, I am getting Excepton:- ‘ java.util.zip.ZipException: incorrect header check’
When i checked the response header it is specified ‘content-encoding:deflate’
Can you please help me out what is the way to convert these kind of response to a string?

Full stack trace of the exception is:
java.util.zip.ZipException: incorrect header check
at java.util.zip.InflaterInputStream.read(InflaterInputStream.java:164)
at org.apache.http.conn.EofSensorInputStream.read(EofSensorInputStream.java:138)
at org.apache.http.conn.EofSensorInputStream$read.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:45)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:108)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:124)
at com.jayway.restassured.internal.RestAssuredResponseOptionsGroovyImpl.convertStreamToByteArray(RestAssuredResponseOptionsGroovyImpl.groovy:429)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite$StaticMetaMethodSiteNoUnwrapNoCoerce.invoke(StaticMetaMethodSite.java:148)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:99)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:53)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:157)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:165)
at com.jayway.restassured.internal.RestAssuredResponseOptionsGroovyImpl.charsetToString(RestAssuredResponseOptionsGroovyImpl.groovy:481)
at com.jayway.restassured.internal.RestAssuredResponseOptionsGroovyImpl$charsetToString$3.callCurrent(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141)
at com.jayway.restassured.internal.RestAssuredResponseOptionsGroovyImpl.asString(RestAssuredResponseOptionsGroovyImpl.groovy:169)
at com.jayway.restassured.internal.RestAssuredResponseOptionsGroovyImpl.asString(RestAssuredResponseOptionsGroovyImpl.groovy:165)
at com.jayway.restassured.internal.RestAssuredResponseOptionsImpl.asString(RestAssuredResponseOptionsImpl.java:193)
at com.se.semtech.datavalidation.test.DslValidationTest.getProductsById(DslValidationTest.java:77)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:84)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:714)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:901)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1231)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at org.testng.TestRunner.privateRun(TestRunner.java:767)
at org.testng.TestRunner.run(TestRunner.java:617)
at org.testng.SuiteRunner.runTest(SuiteRunner.java:334)
at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:329)
at org.testng.SuiteRunner.privateRun(SuiteRunner.java:291)
at org.testng.SuiteRunner.run(SuiteRunner.java:240)
at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:86)
at org.testng.TestNG.runSuitesSequentially(TestNG.java:1224)
at org.testng.TestNG.runSuitesLocally(TestNG.java:1149)
at org.testng.TestNG.run(TestNG.java:1057)
at org.testng.remote.RemoteTestNG.run(RemoteTestNG.java:111)
at org.testng.remote.RemoteTestNG.initAndRun(RemoteTestNG.java:204)
at org.testng.remote.RemoteTestNG.main(RemoteTestNG.java:175)

I’m trying to fetch ‘ID’ attribute’s value from the response and compare it with the value in DB. But when I run the code, the response I get is just this:
{“Status”: “OK”, “Data”:”[ ]”}
The result doesn’t contain any data but it has to return a response with the details of Bob. It returns the correct response when I check it from other tools like Swagger and SoapUI.

Please clarify.

Vijay

Hi James..

I’m trying to match the entire response content of the REST API call using rest assured… Can you help me on this..

Example..
In your case you are matching the number of rides…Instead of that can you tell me how can we match the whole content…

Any help on how to model this for rest-assured would be appreciated.
Thanks,
Tim

Tim

James,
Very strange, I think there is a filter being used in your reply box. In both code cases I show above The Map I’m using is actually
Map of String, Customer with angle brackets. I’m still having problems hope you can help
thanks,
Tim

James,
Thx for the reply. I agree, I just cant figure out what the path to the final map is.
looks like the jersey angle brackets were stripped above also (ooh thats html 😉
works in jersey : response.readEntity(new GenericType < Map < String, Customer > > (){});
seems like it should be similar in RA, don’t you think?

I have tried a dozen paths to get to the “final map” ie Customer, all seem to fail. Looks like I need a wildcard to get me to the
2nd map. Tried “$*”, “$.*”, all are invalid. If you can think of a path that might work or suggest a different way to look at it, let me know.

I have tried the rest-assured forum, no answer for 2months …, I will try again.
Thanks,
Tim

Tim

Just to follow up, I think “$.*” is the correct path. I tested it on both json path test sites and it returns an array , which is the correct
first step. When used in rest-assured it blows up so I filed an issue.
see: unexpected token error for “$.*” path https://github.com/rest-assured/rest-assured/issues/776

thanks,
Tim

Fluent Wait

Hi James,

I have been working with rest assured for last few months. I have created some tutorial please check them out.

That’s a nice post. Is there a way to get value of a particular parameter from the response object instead of converting it to string?
The response object is:
Response response=given()
.body(file)
.with().contentType(“application/json”)
.post(“http://localhost:8080/SpringREST/rest/emp/create”)
.then()
.extract().response();
;
I need to get the value of a parameter called “name” from the above response object.How to do it??

James Willett

Sorry only just saw your post! Let me know if you are still having trouble with this – if so please post an example of the response.

hari naren

Yes..As of now I am converting the response body as string and then i am using JsonPath to again convert it to json object to get the parameter value like below.Is there any better way of doing it?

// We convert the JSON response to a string, and save it in a variable called ‘jsonAsString’
jsonAsString = response.asString();
System.out.println(“response “+jsonAsString);

}
—–> can anyone tell me is this the right code??? to save response and login using param.
—–>

http://james-willett.com James Willett

Not sure I understand the question – your code will call the /login with the “email” and “password” parameters, and then extract whatever response comes back – in this case it needs to be a JSON response for it to be extracted.

Actually, when JSonPathForAttribute= “2017-09-01T03:14:05.000Z” is returning me null and hence no data for “2017-09-01T03:14:05.000Z.bridge_tap” as well. Can you suggest what I am doing wrong ? I am using Eclipse/Java for this.

http://james-willett.com James Willett

I guess its not working because the string is quite long and might contain special characters that need to be escaped.