Deserialize Json Response
This tutorial will talk about a very interesting and helpful technique to read Body from a Response (Deserialize Json Response). This technique is called Deserialization of Response. Serialization and Deserialization are programming techniques where we convert Objects to Byte Streams and from Byte Streams back to Objects.
Before we start, it is very important that you go through the previous set of Tutorials. You can take a look at the tutorials here
- REST Api testing in Rest-Sharp
How to Deserialize JSON Response to Class with Rest Sharp?
Let us continue with our previous chapter Making a POST request using Rest-Sharp. In the previous chapter we made a successful post request and the following Response body was received.
We used JObject.Parse to validate parts of the Response body. Know we will convert this Response body into a Class. Representing a JSON, or any structured data including XML, into a programming class is called Deserialization of JSON. The term Deserialization here means the conversion from String form of JSON to a Class form. This is also called Object Representation of structured data. Here structured data is the JSON.
In order to convert the JSON into a Class representation, we will first create a Class that has all the nodes present in the JSON. The Success response above has two nodes
- SuccessCode
- Message
The value of these two nodes is String. Below image shows the parts of the response.
To represent such a Json we will need a class with two String variables, each representing the node in the Json. Below is the class code. Pay attention to the code comments for finer details
1 2 3 4 5 6 7 8 |
public class ResponseData { // Succes code of response received public string SuccessCode; // Message of response received public string Message; } |
Now we have a ResponseData class that can store all the nodes present in Success Response. Let us understand how we can use RestSharp to automatically convert Response Body Json to the instance of the ResponseData class.
By using deserialize object method of simplejson class, we can get all element nodes from string json to required format which in our case is a class(ResponseData).
SimpleJson.DeserializeObject<Class>(JSon string);
Below is the sample code to deserialze json string to responsedata class.
1 2 |
ResponseData responseData= SimpleJson.DeserializeObject<ResponseData>(restResponse.Content); |
This method call will internally do two things
- Create an instance of ResponseData
- Then copy the Node value of Json to the respective variable in the Class. For e.g. Value of SuccessCodenode to the Variable SucessCode in the class.
To visualize it, let us look at the image below.
Below is the complete code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using RestSharp namespace RestSharpExample { [TestClass] public class UnitTest1 { [TestMethod] public void PostMethod() { RestClient restClient = new RestClient("http://restapi.demoqa.com/customer"); //Creating Json object JObject jObjectbody = new JObject(); jObjectbody.Add("FirstName", "Narayn"); jObjectbody.Add("LastName", "Kaluri"); jObjectbody.Add("UserName", "NaraynKasdfsdfluri"); jObjectbody.Add("Password", "Passwovasdfsdaf23"); jObjectbody.Add("Email", "abcdafsad@hotmail.com"); RestRequest restRequest = new RestRequest("/register" ,Method.POST); //Adding Json body as parameter to the post request restRequest.AddParameter("application/json",jObjectbody,ParameterType.RequestBody); IRestResponse restResponse = restClient.Execute(restRequest); ResponseData responseData=SimpleJson.DeserializeObject<ResponseData>(restResponse.Content); Console.WriteLine(responseData.Message); Console.WriteLine(responseData.SuccessCode); } } public class ResponseData { // Succes code of response received public string SuccessCode; // Message of response received public string Message; } |
Output for above sample code is as shown below.
Now you can use the responseBody variable to apply any assertions that you want or may be pass it as an input to other tests.
Assert.AreEqual(“OPERATION_SUCCESS”, responseData.SuccessCode); Assert. AreEqual (“Operation completed successfully”, responseData.Message); |
Deserializing Response body based on Response Status code
In real life it is possible for a REST Api endpoint to return multiple Json formats. For e.g. the API in this tutorial can return a completely different response in case of Failures. Below is the Json that is returned in failure cases.
{
“FaultId”: “User already exists”, “fault”: “FAULT_USER_ALREADY_EXISTS” } |
If we try to Deserialize this response into ResponseData, it will not work. The reason is that while Deserializing RestSharp will not be able to find SuceessCode and Message fields in the Response body. As a result the two variables will be set to null.
So how do we handle these cases? This particular case of Success and Failure can be easily catered using the returned Status code. API in this tutorial returns 201 status code in case of Success and 200 in case of Error. We will also need another class that represents the failure Json Response.
We can see that there are two nodes that are present in Failure cases.
- FaultId
- Fault
Below is the class that can represent a Failure response.
1 2 3 4 5 |
public class RegistrationFailureResponse { public string FaultId; public string fault; } |
To determine which scenario to execute we can simply put an if check in the Test code. Below is the updated Test code.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using Newtonsoft.Json.Linq; using RestSharp namespace RestSharpExample { [TestClass] public class UnitTest1 { [TestMethod] public void PostMethod() { RestClient restClient = new RestClient("http://restapi.demoqa.com/customer"); //Creating Json object JObject jObjectbody = new JObject(); jObjectbody.Add("FirstName", "Narayn"); jObjectbody.Add("LastName", "Kaluri"); jObjectbody.Add("UserName", "NaraynKasdfsdfluri"); jObjectbody.Add("Password", "Passwovasdfsdaf23"); jObjectbody.Add("Email", "abcdafsad@hotmail.com"); RestRequest restRequest = new RestRequest("/register" ,Method.POST); //Adding Json body as parameter to the post request restRequest.AddParameter("application/json",jObjectbody,ParameterType.RequestBody); IRestResponse restResponse = restClient.Execute(restRequest); ResponseData responseData=SimpleJson.DeserializeObject<ResponseData>(restResponse.Content); if((int)restResponse.StatusCode==200) { // Deserialize the Response body into RegistrationFailureResponse FailureResponse responseBody =SimpleJson.DeserializeObject<FailureResponse>(restResponse.Content); // Use the FailureResponse class instance to Assert the values of Response. Assert.AreEquals("User already exists", responseBody.FaultId); Assert. AreEquals ("FAULT_USER_ALREADY_EXISTS", responseBody.fault); } else if ((int)restResponse.StatusCode==201) { // Deserialize the Response body into SuccessResponse SuccessResponse responseBody =SimpleJson.DeserializeObject< SuccessResponse >(restResponse.Content); // Use the SuccessResponse class instance to Assert the values of Response. Assert.assertEquals("OPERATION_SUCCESS", responseBody.SuccessCode); Assert.assertEquals("Operation completed successfully", responseBody.Message); } } public class SuccessResponse { // Succes code of response received public string SuccessCode; // Message of response received public string Message; } public class FailureResponse { // FaultId of response received public string FaultId; // Fault of response received public string Fault; } |
Note: This is not the most ideal way of handling these types of cases. If possible we should rely on Inheritance to cater to varied Responses being returned by an API endpoint. In coming tutorials we will see how we can implement an inheritance chain to handle these cases.