Assert key name in the json response using groovy - json

I want to assert a key in the json response.
Response
{
"availableRooms": [
{
"roomId": 2,
"exchangeEmailId": null,
"roomName": "Room 1",
"floor": 0,
"groupID": 3,
"defaultCapacity": 8,
"maxCapacity": 8,
"attributes": [
{
"attributeID": 170,
"displayName": "Video Conference Unit",
"abbreviation": "VCU"
}
],
"externalRoomEmail": "vinay.jaiswal#condecosoftware.com"
}
],
"availableRoomsForAllDates": {},
"callResponse": {
"message": null,
"customResponseCode": null
}
}
Groovy
import groovy.json.JsonSlurper
def ResponseMessage = messageExchange.response.responseContent
def jsonSlurper = new JsonSlurper().parseText(ResponseMessage)
if( jsonSlurper.containsKey( 'externalRoomEmail' ) )
{
log.info 'a'
}
else
{
log.info 'b'
}
Output
Tue Nov 24 20:24:35 IST 2020:INFO:b
Is there any inbuilt method?
If I try jsonSlurper.availableRooms.externalRoomEmail then it gives me null but testcase is passed.
I want that it should break the testcase if key not found.

<edit - just re-read your question, answer adjusted accordingly>
First of all I'm going to call your parsed json json instead of jsonSlurper as the slurper is the groovy class used to parse json and it's conceptually confusing to name the data "slurper".
So your problem is that json.availableRooms returns a list. In other words you would have to use something like:
if(json.availableRooms.first().externalRoomEmail) {
...
} else {
...
}
to check if the first room had an externalRoomEmail defined.
From there is depends on what you want to do. Let's say that you wanted to see if any of the available rooms had an externalRoomEmail defined, you would then do something like:
def roomsWithEmails = json.availableRooms.findAll { it.externalRoomEmail }
if (roomsWithEmails) {
roomsWithEmails.each { room ->
println "room ${room.roomName} has external email ${room.externalRoomEmail}"
}
} else { // no rooms with externalRoomEmail
// do something else
}

Related

Groovy Modifying Json

I'm trying to modify a json which I'm reading from a file:
String response = new File("response.json").text
here is what response looks like:
{
"TerminatingInstances": [
{
"InstanceId": "id",
"CurrentState": {
"Code": 32,
"Name": "shutting-down"
},
"PreviousState": {
"Code": 16,
"Name": "running"
}
}
]
}
To modify it I did as follows:
def slurped = new JsonSlurper().parseText(response)
def builder = new JsonBuilder(slurped)
builder.content.TerminatingInstances.InstanceId = "id-updated"
but I get argument type mismatch error, not sure why.
That's because it's an array of instances inside TerminatingInstances
You can either set all of them to the new id with *.:
builder.content.TerminatingInstances*.InstanceId = "id-updated"
Or set just the first one with
builder.content.TerminatingInstances[0].InstanceId = "id-updated"

How do I capture a specific array element from json response into a gherkin cucumber attribute?

Am trying to capture from below json response, the ghi[0] element which is x and assign it to a variable in my BDD in gherkin/cucumber language but it is complaining it can't read property.
This is how am capturing:
* def xyz = response.results.payload.abc.def.ghi
Response
{
"results": {
"payload": {
"abc": [
{
"def": [
{
"ghi": "x",
},
{
"ghi": "y",
},
{
"ghi": "y",
}
]
}
]
}
}
}
This is what its complaining:
features.blah: [1.1:50] blah.feature:30 - evaluation (js) failed: response.results.payload.abc.def.ghi, javax.script.ScriptException: TypeError: Cannot read property "ghi" from undefined in <eval> at line number 1
That's because your access is wrong. This below works:
* def xyz = response.results.payload.abc[0].def[0].ghi
* match xyz == 'x'
That said, if you are lazy to traverse deeply nested data, you can do this:
* def xyz = get[0] $..ghi
* match xyz == 'x'
Please read the docs, it will save you time :) https://github.com/karatelabs/karate#get

Error in JSON array comparison customization(sky-screamer)

I have below two JSONs to compare,
expected json:
[
{
"id": 1,
"code": 1,
"createdOn": null,
"lastModifiedOn": null
},
{
"id": 2,
"code": 1,
"createdOn": null,
"lastModifiedOn": null
}
]
actual json
[
{
"id": 1,
"code": 1,
"createdOn": "2019-12-31",
"lastModifiedOn": "2019-12-31",
},
{
"id": 2,
"code": 1,
"createdOn": "2019-12-31",
"lastModifiedOn": "2019-12-31",
}
]
Trying to compare by ignoring couple of nodes using below code
JSONAssert.assertEquals(actualjson, expectedjson,
new CustomComparator(JSONCompareMode.STRICT,
new Customization("createdOn", (o1, o2) -> {
return true;
}),
new Customization("lastModifiedOn", (o1, o2) -> {
return true;
})
)));
but it is failing with below assertion exception,
java.lang.AssertionError: [0].createdOn
Expected: null
got: 2019-12-31
; [0].lastModifiedOn
Expected: null
got: 2019-12-31
; [1].createdOn
Expected: null
got: 2019-12-31
; [1].lastModifiedOn
Expected: null
got: 2019-12-31
how can I compare array of json values with customization object by skipping createdon and lastmodifiedon nodes?
<groupId>org.assertj</groupId>
<version>2.2.1</version>
Yes below code snippet
JSONAssert.assertEquals(actualjson, expectedjson,
new CustomComparator(JSONCompareMode.STRICT,
new Customization("**.createdOn", (o1, o2) -> true),
new Customization("**.lastModifiedOn", (o1, o2) -> true)
)));
Eventually Customization.getCustomization method invoke appliesToPath method , which invoke this.path.matcher(path).matches();
matcher method is from java.util.regex , so if your pattern "**.createdOn" matches with path "[0].createdOn" , "[1].createdOn" then your Customisation will be added CustomComparator which inturn call your method "(o1, o2) -> true"
Approach 1: Parse the JSON and recreate the two object JSONs without the date properties.
Approach 2: Parse the JSON and put an assertion on each property to be compared.
Give a try to JsonUnit it allows you to ignore values, elements or path which should help.
Since SkyScreamer has open issue noted in github I found temporary solution and thought would be helpful for others,
https://github.com/skyscreamer/JSONassert/issues/109
solution:
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
List<DomainObject> actualDomainObj = mapper.readValue(actualJson, new TypeReference<List<DomainObject>>() {
});
List<DomainObject> expectedDomainObj = mapper.readValue(expectedJson, new TypeReference<List<DomainObject>>() {
});
assertDomainObjResults(actualDomainObj.get(0), expectedDomainObj.get(0));
private void assertDomainObjResults(DomainObject actual, DomainObject expected) {
softAssertions.assertThat(actual.getId()).isEqualTo(expected.getId());
softAssertions.assertThat(actual.getLastModifiedOn()).isEqualTo(LocalDate.now());
softAssertions.assertThat(actual.getCreatedOn()).isEqualTo(LocalDate.now());
}
accept the answer if someone finds it useful.
I recently created a custom comparator that lets you use regular expressions in the 'expected' JSON:
public class ExtendedJsonComparator extends DefaultComparator {
public ExtendedJsonComparator(JSONCompareMode mode) {
super(mode);
}
#Override
public void compareValues(String prefix, Object expectedValue, Object actualValue, JSONCompareResult result) throws JSONException {
String expected = expectedValue.toString().trim();
String actual = actualValue.toString();
if(expected.startsWith("${") && expected.endsWith("}")) {
String regex = expected.substring(2, expected.length() - 1);
if(!actual.matches(regex)) {
result.fail(prefix, expected, actual);
}
} else {
super.compareValues(prefix, expectedValue, actualValue, result);
}
}
}
For 'expected, you can then do the following, or create a regex to match your date format, if that's something you're testing:
[
{
"id": 1,
"code": 1,
"createdOn": "${.*}",
"lastModifiedOn": "${.*}"
},
{
"id": 2,
"code": 1,
"createdOn": "${.*}",
"lastModifiedOn": "${.*}"
}
]

How can i Parse JSON data values present at any level in GROOVY

Following is my Parsed JSON with json Surplur . i has been required for SOAPUI scripts to manupulate
{buildInfo={application=RepCatalog, buildDate=Thu Oct 13 17:01:48 IST 2016, version=1.0.0}, data={Reps=[{cascadeCount=0, catalogRep={RepId=48961, RepType=REPORT, initialCreation=10/13/2016 20:39:11, lastAccessed=10/13/2016 20:39:11, lastModified=10/13/2016 20:39:11, parentRep={RepId=48962, RepType=REPORT, initialCreation=10/13/2016 20:39:14, lastAccessed=10/13/2016 20:39:14, lastModified=10/13/2016 20:39:14, status=OPEN, title=REPORT1476371359504}, rights=[{availability=PUBLIC, isDefault=true}], status=OPEN, title=REPORT1476371357505, userTags=[PRIVATE1476371349835]}, status=success}]}, status=success, summary={apiName=Integration Service, partialRepSucceeded=0, totalRepFailed=0, totalRepProccessed=1, totalRepSucceeded=1}, time=6674}
Following is unparsed JSON
{
"summary": {
"apiName": "Integration Service",
"totalRepProccessed": 1,
"totalRepFailed": 0,
"totalRepSucceeded": 1,
"partialRepSucceeded": 0
},
"buildInfo": {
"application": "RepCatalog",
"version": "1.0.0",
"buildDate": "Thu Oct 13 17:01:48 IST 2016"
},
"status": "success",
"data": {"Reps": [ {
"status": "success",
"catalogRep": {
"RepId": 48961,
"RepType": "REPORT",
"title": "REPORT1476371357505",
"rights": [ {
"availability": "PUBLIC",
"isDefault": true
}],
"initialCreation": "10/13/2016 20:39:11",
"lastModified": "10/13/2016 20:39:11",
"lastAccessed": "10/13/2016 20:39:11",
"status": "OPEN",
"parentRep": {
"RepId": 48962,
"RepType": "REPORT",
"title": "REPORT1476371359504",
"status": "OPEN"
},
"userTags": ["PRIVATE1476371349835"]
},
"cascadeCount": 0
}]},
"time": 6674
}
I want to parse it to get values of All RepId in above in groovy SOAPUI
Given your input as a string variable called json, the following script:
def extractRepIds (def tree, def ids = []) {
switch (tree) {
case Map:
tree.each { k, v ->
if (k == "RepId") { ids << v }
extractRepIds(v, ids)
}
return ids
case Collection:
tree.each { e -> extractRepIds(e, ids) }
return ids
default :
return ids
}
}
def extractRepIdsFromJson(def jsonString) {
def tree = new JsonSlurper().parseText(jsonString)
extractRepIds(tree)
}
println extractRepIdsFromJson(json)
produces the following results:
[48961, 48962]
Alternate Solution
The extractRepIds method can be written somewhat more cleanly by using the inject() method:
def extractRepIds (def tree) {
switch (tree) {
case Map:
return tree.inject([]) { list, k, v ->
list + (k == "RepId" ? [v] : extractRepIds(v))
}
case Collection:
return tree.inject([]) { list, e ->
list + extractRepIds(e)
}
default :
return []
}
}
With all else being the same, this yields the same results.
If you want to find all occurrences in a file, you can use regular expressions. It may be useful in this case.
def pattern = ~'\"RepId\":\\s(\\d+)' //"RepId": 48961
def path = "/tmp/data.json"
def data = new File(path).text
def repIds = []
pattern.matcher(data).findAll{fullMatch,repId ->
repIds << repId
}

How to get array number with groovy script in SoapUI?

I want to assert the value of a property in Json response with the use of Groovy script in SoapUI. I know a value for name but I need to know on which position the id is.
json response example:
{
"names":[
{
"id":1,
"name":"Ted"
},
{
"id":2,
"name":"Ray"
},
{
"id":3,
"name":"Kev"
}
]
}
Let's say I know that there is a name Ray, I want the position and the id (names[1].id)
Here is the script to find the same:
import groovy.json.*
//Using the fixed json to explain how you can retrive the data
//Of couse, you can also use dynamic value that you get
def response = '''{"names": [ { "id": 1, "name": "Ted", }, { "id": 2, "name": "Ray", }, { "id": 3, "name": "Kev", } ]}'''
//Parse the json string and get the names
def names = new JsonSlurper().parseText(response).names
//retrive the id value when name is Ray
def rayId = names.find{it.name == 'Ray'}.id
log.info "Id of Ray is : ${rayId}"
//Another way to get both position and id
names.eachWithIndex { element, index ->
if (element.name == 'Ray') {
log.info "Position : $index, And Id is : ${element.id}"
}
}
You can see here the output