JSONAssert on part of JSON from RESTAssured JSONPath

1,332 views
Skip to first unread message

Rob Powell

unread,
Jun 25, 2018, 12:17:50 AM6/25/18
to REST assured
I am able to retrieve JSON from a service using RESTAssured.

I would like to use the JSONPath capability to extract JSON and then compare it using JSONAssert.

Here's my example:

    @Test
   
public void doAPITestExample() throws JSONException {
       
Response response = RestAssured.given()
               
.log().all()
               
.get("http://localhost:8081/mockservice");
        response
.then()
               
.log().all()
               
.assertThat().statusCode(200);


       
String body = response.getBody().asString();
       
System.out.println("Body:" + body);
       
/*
            {"datetime": "2018-06-21 17:48:07.488384", "data": [{"foo": "bar"}, {"test": "this is test data"}]}
        */



       
// able to compare entire body with JSONAssert, strict=false
       
Object data = response.then().extract().path("data");
       
System.out.println("Response data:");
       
System.out.println(data.getClass()); // class java.util.ArrayList
       
System.out.println(data.toString());


       
// JSONAssert data with strict=false
       
String expectedJSON = "{\"data\":[{\"foo\": \"bar\"}, {\"test\": \"this is test data\"}]}";
       
JSONAssert.assertEquals(expectedJSON, response.getBody().asString(), false);


       
// How do I extract JSON with JSONPath, use JSONAssert together?
   
}


Approach 1 - using JSONPath to get JSONObject

How do I get JSONPath to return a JSONObject that can be used by JSONAssert?

In the code example:

    Object data = response.then().extract().path("data");


This returns a java.util.ArrayList.  How can this be used with JSONAssert to compare to expected JSON?


Approach 2 - parse extracted data with JSONParser

If I do data.toString(), this returns a string that cannot be parsed due to lack of quote handling for string values with spaces strings:

    String dataString = response.then().extract().path("data").toString();
   
JSONArray dataArray = (JSONArray) JSONParser.parseJSON(dataString);

Result:

    org.json.JSONException: Unterminated object at character 24 of [{foo=bar}, {test=this is test data}]


Approach 3 - Using JSON schema validation

Is is possible to extract just the `data` property from the JSON and run that against JSON Schema on just that part?


Please let me know what is a good approach to do this.

I have sample test code and some simple mock services for this on request.

-Rob

Johan Haleby

unread,
Jun 25, 2018, 3:17:39 AM6/25/18
to rest-a...@googlegroups.com
Hi!

When you "extract" Rest Assured will not return JSON but rather JSON mapped to another datastructure. So in your case it'll return a list of map's representing the json. What you want to do is to extract the entire string (asString()). This is as far as REST Assured will help you. It won't help you extract parts of the response to a JSON document.

Regards,
/Johan

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Rob Powell

unread,
Jun 25, 2018, 10:55:07 AM6/25/18
to REST assured
Hi Johan;

Please see details in Approach 2 - parse extracted data with JSONParser


If I do data.toString(), this returns a string that cannot be parsed due to lack of quote handling for string values with spaces strings:

    String dataString = response.then().extract().path("data").toString();
    
JSONArray dataArray = (JSONArray) JSONParser.parseJSON(dataString);

Result:

    org.json.JSONException: Unterminated object at character 24 of [{foo=bar}, {test=this is test data}]

I am investigating this, but I believe this is a behavior in JsonPath - part of how the JsonProvider behaves;
( reference: https://github.com/json-path/JsonPath#jsonprovider-spi )  I haven't figured this out yet.

My adventure continues;
-Rob

Johan Haleby

unread,
Jun 27, 2018, 2:23:47 AM6/27/18
to rest-a...@googlegroups.com
Please see details in Approach 2 - parse extracted data with JSONParser

Yes I saw that and I tried to explain the reason for it, i.e. it doesn't return a JSON string. You have to extract all data, i.e.

String jsonString = response.asString();

Now you can use any library you like to extract the "data" object.

Regards,
/Johan

Rob Powell

unread,
Jun 30, 2018, 3:49:11 PM6/30/18
to REST assured
Hi Johan;

Can you recommend a good library that will do that?

I understand parsing the response as a string to create JSONPath:

  responseJsonPath = JsonPath.parse(response.asString());

But I am still stuck trying to extract "data" as JSON.

-Rob

Johan Haleby

unread,
Jul 1, 2018, 3:12:15 AM7/1/18
to rest-a...@googlegroups.com
I think you can use Jackson, I don't remember off the top of my head how this is done but it should be google:able.

Rob Powell

unread,
Jul 1, 2018, 12:56:02 PM7/1/18
to REST assured
I've figured out a work-around:
* use RESTAssured/JSONPath to extract the property
* use Gson to marshal the Java Object back to JSONArray/JSONObject
* use JSONAssert on the JSONObject

        /*
            {"datetime": "2018-06-30 19:10:38.402387", "data": [{"foo": "bar"}, {"bash": {"one": "this is a test string", "two": 123, "three": [1, 2, 3]}}]}
        */
        
        // able to compare entire body with JSONAssert, strict=false
        String expectedJSON = "{\"data\": [{\"foo\": \"bar\"}, {\"bash\": {\"one\": \"this is a test string\", \"two\": 123, \"three\": [1, 2, 3]}}]}";
        JSONAssert.assertEquals(expectedJSON, response.getBody().asString(), false);

        // extract and convert JSONArray using Gson
        GsonBuilder gsonBuilder = new GsonBuilder();
        Gson gson = gsonBuilder.create();

        String dataJSONArrayString = gson.toJson((ArrayList)response.then().extract().path("data"));
        JSONArray dataJSONArray = (JSONArray) JSONParser.parseJSON(dataJSONArrayString);
        System.out.println("data property:" + dataJSONArray.toString());

        String expectedDataJSONArrayAsString = "[{\"foo\": \"bar\"}, {\"bash\": {\"one\": \"this is a test string\", \"two\": 123, \"three\": [1, 2, 3]}}]";
        JSONAssert.assertEquals(expectedDataJSONArrayAsString, dataJSONArray, true);

-Rob

Johan Haleby

unread,
Jul 2, 2018, 6:27:37 AM7/2/18
to rest-a...@googlegroups.com
Thanks for sharing.

If you're using Kotlin I think it should be possible to create an extension function quite easily that makes integration with JsonAssert much simpler.

ravi ranjan

unread,
Jul 3, 2018, 8:44:04 AM7/3/18
to REST assured
when trying to download rest-assured-3.1.0-dist.zip is showing Virus threat for this and windows is not allowing me to install it. Using windows 10. I tried 2 times and same virus threat was showing and unable to install it.

Johan Haleby

unread,
Jul 3, 2018, 8:48:04 AM7/3/18
to rest-a...@googlegroups.com
I've heard this as well but I think it's a false positive. But I'd be happy confirm this. I'm using macosx and using maven to create the zip files.

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.
--
Sent from my phone

Ankit Gupta

unread,
Jul 5, 2018, 4:53:10 AM7/5/18
to rest-a...@googlegroups.com
I shared my answer on below link:


Maybe it would solve your problem.

To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured+unsubscribe@googlegroups.com.

For more options, visit https://groups.google.com/d/optout.
--
Sent from my phone

--
You received this message because you are subscribed to the Google Groups "REST assured" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rest-assured+unsubscribe@googlegroups.com.

Riyas Valiya

unread,
Sep 1, 2018, 10:31:41 AM9/1/18
to REST assured
Depending on what you want to do with the extracted part, you may be able to use the SameJSONAs hamcrest matcher from here
For example:

response().then().body("data", SameJSONAs("[{\"foo\": \"bar\"}, {\"test\": \"this is test data\"}]").allowAnyArrayOrdering())

Riyas Valiya

unread,
Sep 4, 2018, 10:51:04 AM9/4/18
to REST assured
Apologies, I think I jumped the gun there. The SameJSONAs matcher only works with Strings, so while you are able to do things like:

response().then().body(SameJSONAs(expectedJsonString).allowAnyArrayOrdering())

to match the entire body, you are not able to extract parts of it to match because once you extract, rest-assured returns either an ArrayList or a HashMap depending upon whether the path extracted is a JSON array or object. 
I have only used it to match the entire payload. 

On Monday, June 25, 2018 at 12:17:50 AM UTC-4, Rob Powell wrote:

Rob Powell

unread,
Sep 5, 2018, 12:44:13 AM9/5/18
to rest-a...@googlegroups.com
Right - and that was the problem I was encountering - I wanted to match to what can be selected using the JSONPath methods.

I did have a work-around with using Gson to handle massaging back to a String, but that can be problematic in itself.

Maybe if I figure out how rest-assured can mock JSONPath from String, and use the same methodology...
-Rob


--
You received this message because you are subscribed to a topic in the Google Groups "REST assured" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/rest-assured/nwUnYq5KdTk/unsubscribe.
To unsubscribe from this group and all its topics, send an email to rest-assured...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages