I have a json like below
{
"hasErrorResponse": "false",
"responseObject": [{
"success": true,
"errorMessage": null,
"availablity": "YES",
"errorCode": null,
"availableQtys": 1234,
"prId": "451667"
}]
}
Now using RestAssured if I do
response.then().assertThat().body("responseObject.prId", equalTo("451667"));
It's failing because it says Expected: 451667 but Got: [451667]
I guess it's because it's getting the prId attribute as an ArrayList and not as String. How do I go about validating this sceanrio?
hasItems matcher works to validate anything inside collection
Related
I have a simple python (version 3.10.2) script that uses the requests library to make a REST call to an API. The call returns a list of objects. I find that the json.loads() function will not parse the JSON returned in the response. It gives me the following error:
TypeError: the JSON object must be str, bytes or bytearray, not list
Oddly, the json.dumps() function can successfully format the same data.
Here is the code:
import requests
import json
def get_groups(url):
# TODO SSL/TLS turned OFF (verify=False)
response = requests.get(url + "/groups", verify=False)
print("status code:", response.status_code)
print("JSON:\n")
print(json.dumps(response.json(), indent=2))
json.loads(response.json())
Here is an example what json.dumps() is outputting:
[
{
"id": 6,
"web_url": "https://<URL redacted>/groups/test",
"name": "test",
"path": "test",
"description": "",
"visibility": "public",
"share_with_group_lock": false,
"require_two_factor_authentication": false,
"two_factor_grace_period": 48,
"project_creation_level": "developer",
"auto_devops_enabled": null,
"subgroup_creation_level": "maintainer",
"emails_disabled": null,
"mentions_disabled": null,
"lfs_enabled": true,
"default_branch_protection": 2,
"avatar_url": null,
"request_access_enabled": true,
"full_name": "test",
"full_path": "test",
"created_at": "2021-08-03T15:41:34.523Z",
"parent_id": null,
"ldap_cn": null,
"ldap_access": null
}
]
I have seen lots of postings about this and every one mentions using json.loads() to parse the JSON data. Not sure why it works for them, but it doesn't work for me.
Any ideas as to what is wrong?
As was pointed out by #tkausl, in this case the HTTP/REST response object returns the JSON data already parsed. For some reason I missed that. I don't need to to use the json library.
I am getting the following string through an API request:
{
"id": 21,
"description": null,
"creationDate": "2020-01-20T00:00:00",
"status": "string",
"open": false,
"confirmedBy": null,
"solvedDate": "0001-01-01T00:00:00",
"repairedBy": null,
"works": false,
"brokenParts": [],
"wellId": 9
}
Now, I try to create an object from this:
var result = json.decode(response.body);
I receive the following error:
type '_TypeError' is not a subtype of type 'String'
Why does this happen? The JSON is valid.
When receiving information from an online source, it's actually not a String variable you're receiving (even though it can be printed that way, it's not formatted correctly). It's actually what's called a "response" variable. And you need to convert that to a Map to be able to break it up into Strings.
For Example:
Map result = jsonDecode(response.body);
String tempString = result['id'];
Would get you the value of the "id" variable inside the Map.
I have two requests that return response with similar JSON structure. When I try to use JSON extractor on one, it works properly but when I try to extract value in the same way from the second one, it doesn't work. But let's cut to the chase.
My first response looks like this:
{
"values": [
{
"id": 1,
"name": "Fendi",
"logoId": null,
"belongsToUser": true
},
{
"id": 2,
"name": "Jean Paul Gaultier",
"logoId": null,
"belongsToUser": true
},
{
"id": 3,
"name": "Nike",
"logoId": null,
"belongsToUser": false
},
{
"id": 4,
"name": "Adidas",
"logoId": null,
"belongsToUser": true
}
]
}
And I try to extract ID of the object that "belongsToUser": false in this JSON Extractor:
JSON path expression: values[?(#.belongsToUser == false)].id
Match No.: 0
Default Values: null
And it works perfecty fine.
However, when I try this way on my second response, it doesn't work.
The response looks like this:
{
"values": [
{
"id": 12,
"brandName": "Fendi",
"productCategoryName": "Shoes",
"size": "38",
"colorNames": [
"color_green"
],
"date": 1536537600000,
"imageId": null,
"title": "Money",
"numberOfOffers": 0,
"status": "ONGOING"
},
{
"id": 13,
"brandName": "Fendi",
"productCategoryName": "Shoes",
"size": "38",
"colorNames": [
"color_green"
],
"date": 1536537600000,
"imageId": null,
"title": "Exchange",
"numberOfOffers": 0,
"status": "ONGOING"
}
]
}
I try to get id of object that has title variable = "Money" with JSON extractor:
JSON path expression: values[?(#.title == 'Money')].id
Match No.: 0
Default Values: null
But it doesn't find id value and sets my JMeter variable to null.
I also tried to leave Money unquoted or in double quotes and tried different JSON path expresions, like
$.values[?(#.title == 'Money')].id
$..[?(#.title == 'Money')].id
$.[?(#.title == 'Money')].id
But none of these seems to work. Do you have any idea how my JSON path expression shoud look to work properly?
And why doesn't it work in second case when it works in first? Is it because objets in second response have inside array?
I have used your code and it is giving the correct results. Please check the below images.
I have tried with version 3.1 also and it is working fine.
Hope this helps.
Check the below image for different types of options in view result tree.
The $..[?(#.title == 'Money')].id expression should work just fine:
Most probably your JMeter installation is corrupt and you experience some form of jar hell due to some clashing library in JMeter Classpath (it might be caused by presence of deprecated JSON Plugins or similar) . So I would recommend obtaining clean latest version of JMeter and trying out your test on it. If you're using any plugins - install them using JMeter Plugin Manager
If you are not in position to re-install JMeter you can try to get to the bottom of the issue by looking into jmeter.log file. If there are no suspicious entries - add the next line to log4j2.xml file:
<Logger name="org.apache.jmeter.extractor.json" level="debug" />
I have the following response coming from a request
[
{
"id": 3767,
"sellerName": "abc",
"siteActivity": [
{
"siteId": -1,
"siteName": "example.com",
"categories": [
{
"categoryId": 79654,
"parentId": null,
"name": "Photo & Picture Frames",
"siteName": null,
"channelType": null
},
{
"categoryId": 114397,
"parentId": null,
"name": "Chests of Drawers",
"siteName": null,
"channelType": null
},
{
"categoryId": 11707,
"parentId": null,
"name": "Jewellery Boxes",
"siteName": null,
"channelType": null
},
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
},
{
"id": 118156,
"sellerName": "xyz",
"siteActivity": [
{
"categoryId": 45505,
"parentId": null,
"name": "Serving Trays",
"siteName": null,
"channelType": null
}
]
}
]
Now, I need to extract "id" values and "categoryId" values and send them as list in the next request body.
Currently, I am using JSON Path Extractor with the expression
$.[*].id
to get my hand on all ids and
$.[*].siteActivity.[categoryId]
for category ids.
Next, I want to use the above values and send them as parameters in request body.
Currently, I am able to extract only one id with
$.[0].id
and then assigning it to variable "id" and using the following in request body
{"ids":[{"id":"${id}"}]}
but I want to be able to send
{"ids":[{"id":"${id}"},{"id":"${id2}"}....]}
There is no limit on how many ids can be there, so I cannot hardcode and need something dynamic to do the aggregation. What kind of processor can help me here? Please add some example if you can.
I believe that you should be able to use Beanshell PostProcessor for building the request.
Given your sample data your $.[*].id JSONPath Expression should return the following values:
id=[3767,118156]
id_1=3767
id_2=118156
So basically you need to:
Determine "id" count
Populate dynamic JSON Object to send
Store it to JMeter variable for later use
In order to do so add a Beanshell PostProcessor after JSONPath Extractor and put the following code into its "Script" area
import net.sf.json.JSONArray;
import net.sf.json.JSONObject; // necessary imports
JSONObject data2Send = new JSONObject();
JSONArray array = new JSONArray(); // instantiate JSON-related classes
int idCount = vars.get("id").split(",").length; // get "id" variables count
for (int i = 1; i <= idCount; i++) { // for each "id" variable
JSONObject id = new JSONObject(); // construct a new JSON Object
id.put("id", vars.get("id_" + i));// with name "id" and value id_X
array.add(id); // add object to array
}
data2Send.put("ids",array); // add array to "ids" JSON Object
vars.put("myJSON", data2Send.toString()); // store value as "myJSON" variable
You can refer to your {"ids":[{"id":"3767"},{"id":"118156"}]} data as ${myJSON} where required.
The approach will play for any number of "id" variables.
References:
Welcome to Json-lib
How to use json-lib
Json-lib JavaDoc
How to use BeanShell: JMeter's favorite built-in component
Should be a no brainer, but I'm can't seem to access the elements returned from Newtonsoft's json deserializer.
Example json:
{
"ns0:Test": {
"xmlns:ns0": "http:/someurl",
"RecordCount": "6",
"Record": [{
"aaa": "1",
"bbb": "2",
},
{
"aaa": "1",
"bbb": "2",
}]
}
}
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(somestring);
Stripping out the json up to the Record text, i can access the data without issue.
i.e. result.Recordcount
If i leave the json as shown above, can someone enlighten me how to access Recordcount?
All inputs appreciated. Thanks!
For those JSON properties that have punctuation characters or spaces (such that they cannot be made into valid C# property names), you can use square bracket syntax to access them.
Try this:
int count = result["ns0:Test"].RecordCount;