On the server I have a .properties file with the following structure
foo.0.a = foo0A
foo.0.b = foo0B
foo.1.a = foo1A
foo.1.b = foo1B
...
bar.0.a = bar0a
bar.0.b = bar0b
...
I'm using Volley to fetch the file from the server as JSONObject but the output is being returned in the following form
"properties": [
{
"key": "foo.0.a",
"type": "text/plain",
"value": "foo0A"
},
{
"key": "bar.0.a",
"type": "text/plain",
"value": "bar0a"
},
]
This is not the format I'm looking for, and I think it is not convenient anyway.
The wanted format is something like this:
{
"foo": [
{
"id": 0,
"a": "foo0a",
"b": "foo0b"
}, ...
]
"bar": [
{
"id": 0,
"a": "bar0a",
"b": "bar0b"
}, ...
]
}
My question: Should the properties' structure be changed? Or this can be solved by some code on the client side? If it should be changed, what is the best structure?
Related
Dears,
I am working on creating a simple method which will take String argument which will be a path or other kind "pointer" to attribute/s in JSON and this method will remove those attribute/s.
My problem is I can find values of those attribute/s using JsonPath, but I can't find methods in rest assured (or other libraries) which could remove/delete attributes by given path.
JSON is already added earlier so i need to pull him from RequestSpecification or FilterableRequestSpecification object ex.
RequestSpecification rs = *objFromContext*;
FilterableRequestSpecification frs= (FilterableRequestSpecification) rs;
frs.getBody();
I've tried to work with JSONObject class and remove() but it doesn't work on complex JSONs.
given example JSON
{
"created": "string",
"updated": "string",
"items": [
{
"code": "TEST",
"nested": {
"code": "test",
"name": "name",
"other": [
{
"code": "TEST",
"name": "myName",
"quantity": 1
}
]
},
"itemsProperties": [
{
"code": "value1",
"name": "name",
"value": 123
}
]
},
{
"code": "TEST",
"nested": {
"code": "test",
"name": "name",
"other": [
{
"code": "TEST",
"name": "myName",
"quantity": 1
}
]
},
"itemsProperties": [
{
"code": "value2",
"name": "name",
"value": 123
}
]
}
],
"timer": {
"startDate": "2015-01-01",
"endDate": "2021-01-02"
},
"id": "myId"
}
using JsonPath jp = JsonPath.from(httpRequest.getBody().toString());
and then jp.get(items.itemsproperties.code) i can find value1 and value2.
I stuck in this point: How to remove those attributes from sended body?
I know i can convert body into JSONObject and then go field after field conversion between getJSONArray and GetJSONOBject and remove those fields, but i would like to make this metod much more universal.
Is this possible?
If you want to manipulate json in Rest-Assured JsonPath, then the answer is No. You can't do that. JsonPath help you to extract value from json, that's it, no more.
You have to use different libraries to remove key-value pair.
For example: using JsonPath Jayway
DocumentContext parse = JsonPath.parse(body);
parse.delete("$..itemsProperties..code");
System.out.println(parse.jsonString());
How can I stress test POST multiple Body with specified body data?
Here are my Body Data:
{
"car": {
"brand": "toyota",
"model": "avanza",
},
"customer_id": "string"
}
How can I stress test it with multiple body from that ?
example like this one:
{
"car": {
"brand": "toyota",
"model": "avanza",
},
"customer_id": "string"
}
{
"car": {
"brand": "daihatsu",
"model": "xenia",
},
"customer_id": "string"
}
{
"car": {
"brand": "suzuki",
"model": "ertiga",
},
"customer_id": "string"
}
I have tried using User Defined Variables, but I can't use this one because I need specific body data from brand and model. Not like this brand = toyota, model = ertiga
First of all you need to store these brand/model pairs somewhere, i.e. in a file which looks like:
toyota,avanza
suzuki,ertiga
daihatsu,xenia
Second, you need to generate the request body JSON (by the way, your example is not valid, my code snippet assumes the following output:
[
{
"car": {
"brand": "toyota",
"model": "avanza"
},
"customer_id": "string"
},
{
"car": {
"brand": "daihatsu",
"model": "xenia"
},
"customer_id": "string"
},
{
"car": {
"brand": "suzuki",
"model": "ertiga"
},
"customer_id": "string"
}
]
Add JSR223 PreProcessor as a child of the request you want to parameterize and put the following code into "Script" area:
def payload = []
new File('test.csv').readLines().each { line ->
def car = [:]
car.put('brand', line.split(',')[0])
car.put('model', line.split(',')[1])
def car_entry = [:]
car_entry.put('car', car)
car_entry.put('customer_id', 'string')
payload.add(car_entry)
}
vars.put('payload', new groovy.json.JsonBuilder(payload).toPrettyString())
That's it, you should be able to refer the generated request body as ${payload} JMeter Variable where required
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It
You can parametrize band/model and try to read in form csv file
so your body will be as below
"car": {
"brand": "${BRAND}",
"model": "${MODEL}"},
"customer_id": "string"}
Your csv file will be as below
BRAND,MODEL
toyota,avanza
suzuki,ertiga
daihatsu,xenia
to read data from CSV check out CSV_Data_Set_Config
I am using jsonpath to filter.
Json(Dummy json just to explain) source String, which is basically a list of Operating systems and details of its programs etc. In this example, the OS whose id = 1403 is a windows 10 OS and has 2 features acchritecture and browser. There are more details to the browser feature as shown in json
[
{
"id": 1403,
"os": "window 10",
"features": [
{
"id": 1356,
"name": "architecture",
"value": [
{
"id": 1308,
"feature": [
{
"id": 1262,
"key": "name",
"value": "amd64"
}
]
}
],
"category": "cat1"
},
{
"id": 1357,
"name": "browser",
"value": [
{
"id": 1309,
"feature": [
{
"id": 1263,
"key": "name",
"value": "Firefox"
},
{
"id": 1265,
"key": "version",
"value": "187"
}
]
}
],
"category": "cat2"
}
]
},
{
"id": 2804,
"os": "window 7",
"features": [
{
"id": 2764,
"name": "architecture",
"value": [
{
"id": 2719,
"feature": [
{
"id": 2679,
"key": "name",
"value": "amd64"
}
]
}
],
"category": "cat1"
},
{
"id": 2765,
"name": "browser",
"value": [
{
"id": 2722,
"feature": [
{
"id": 2685,
"key": "name",
"value": "Chrome"
},
{
"id": 2684,
"key": "version",
"value": "87.0.4280.88"
}
]
}
],
"category": "cat2"
}
]
}
]
I want to be able to filter the json such that
features[*].name == 'browser' and features[*].value[*].feature[*].value == 'chrome'
What will be the JsonPath string that can help me achieve above query? The above query uses similar syntax used by JsonPath string but doesn't do the job. Its just to explain.
There is another example here gets Movie Title Given 'Starring' field
And would like to get the full OS json that fulfils this condition. In this case a array of OS which contains only one OS i.e. with id= 2804
[
{
"id": "2804",
...
}
]
I am stuck much before what aim to achieve. Here is my code to get all the OS that have "name=browser". I get the array but it only contains value[] items. I want it get the full json. It returns object with IDs- 1357, 2765.
List<Map<String, Object>> expensive = JsonPath.parse(jsonDataSourceString)
.read("$[*].features[*].[?(#.name == 'browser')]");
To get the outer array you need to use the filter like $[?(...)]
For your current use case, we need to use nested array filters. There is an open issue in JsonPath for filter on children level. (Refer here).
Luckily, there is a workaround suggested to use contains over here.
we can use the below expression to filter:
List<Object> expensive = JsonPath.parse(jsonDataSourceString)
.read("$[?(#.features[?(#.name == 'browser')].value[*].feature[*].value contains 'Chrome')]");
Prints the below output
{id=2804, os=window 7, features=[{"id":2764,"name":"architecture","value":[{"id":2719,"feature":[{"id":2679,"key":"name","value":"amd64"}]}],"category":"cat1"},{"id":2765,"name":"browser","value":[{"id":2722,"feature":[{"id":2685,"key":"name","value":"Chrome"},{"id":2684,"key":"version","value":"87.0.4280.88"}]}],"category":"cat2"}]}
I have a json response something like this:
"results": [
{
"id": "1",
"name": "YYY",
"shortName": "Y"
},
{
"id": "2",
"name": "XXX",
"shortName": "X"
},
{
"id": "3",
"name": "ZZZ",
"shortName": "Z"
}
]
I want to get id value when I send name value. For example if name = ZZZ return me id value in this case 3 using rest assured
Json path json-path-2.9.0 with rest-assured
import static com.jayway.restassured.path.json.JsonPath.from;
below JsonPath query
from(response).getList("results.findAll { it.name=='ZZZ' }.id").toString() //returns 3
from(response).getList("results.findAll { it.name=='XXX' }.id").toString() //returns 2
I am really struggling to figure something out in a piece of code I'm working on to pass through a string to multi level JSON. I know that groovy will treat example ="multi.level "$example" as one single property and I have been trying to figure out how to split the string keep the delimiter and then add it to an if statement without any success. I have looked at other solutions but am unable to get them to work in my case... Any help would be appreciated.
JSON:
scriptOutput: [
{
"id": 1,
"data": {
"name": "fyre-discard-vm-1007"
},
"key": "ABCDE123"
},
{
"id": 2,
"data": {
"name": "fyre-discard-vm-1008"
},
"key": "ABCYRE123"
},
{
"id": 3,
"data": {
"name": "fyre-discard-vm-1009"
},
"key": "AZREDE123"
},
{
"id": 4,
"data": {
"name": "fyre-discard-vm-1010"
},
"key": "YTNER857"
},
{
"id": 5,
"data": {
"name": "fyre-discard-vm-1011"
},
"key": "YANT76563A"
},
{
"id": 6,
"data": {
"name": "fyre-discard-vm-1012"
},
"key": "DYAN31685"
},
{
"id": 7,
"data": {
"name": "fyre-discard-vm-1013"
},
"key": "SANF84923"
},
{
"id": 8,
"data": {
"name": "fyre-discard-vm-1014"
},
"key": "SADNS57985"
},
{
"id": 9,
"data": {
"name": "fyre-discard-vm-1015"
},
"key": "DYUIK89OP"
},
{
"id": 10,
"data": {
"name": "fyre-discard-vm-1016"
},
"key": "DHJMNNB6547"
}
]
CODE
#!/usr/local/bin/groovy
import groovy.json.*
def proc7 = "curl https://my-json-server.typicode.com/owainow/privateAPI/machines".execute().text
def slaveList = ["fyre-discard-vm-1007","fyre-discard-vm-1015","fyre-discard-vm-1016"]
def deleteMap=[:]
def jsonName = "data.name"
println "scriptOutput: ${proc7}"
def json = new groovy.json.JsonSlurper().parseText(proc7)
for (slave in slaveList)
{
println(slave);
if (json.find{it.data.name==slave}){ //This works as the properties are passed through as properties
id = json.find{it.data.name==slave}.key
deleteMap = deleteMap+[(slave):(id)]
// I would like to do something like this however I cannot figure out how to split my properties and pass them through in a way that works
/* if (json.find{it."$jsonName"==slave}){ SOMEHOW expand or split jsonName here
id = json.find{it."$jsonName"==slave}.key
deleteMap = deleteMap+[(slave):(id)] */
println "Match"
println (id)
println deleteMap;
}
else{
println"No"
}
}
Cheers guys.
why do you need this? why jsonName should be a string?
Asking this because to get deleteMap from json is quite simple groovy expression:
def deleteMap= json.findAll{ it.data.name in slaveList }.collectEntries{ [it.id, it.data.name] }
however, if you still need it - groovy supports dynamic expression evaluation:
def jsonName = "ROOT.data.name"
def deleteMap= json.findAll{ Eval.me('ROOT', it, jsonName) in slaveList }.collectEntries{ [it.id, Eval.me('ROOT', it, jsonName)] }
I was going to suggest to use the getAt() operator
it[jsonName]
but it turns out that you have a bug in your code, apparently:
id = json.find{it."${jsonName}"==slave}.key
should be
id = json.find{it.data."${jsonName}"==slave}.key
I would still probably use
id = json.find{it.data[jsonName]==slave}.key
Here's complete, corrected snippet:
import groovy.json.*
def proc7 = "curl https://my-json-server.typicode.com/owainow/privateAPI/machines".execute().text
def slaveList = ["fyre-discard-vm-1007","fyre-discard-vm-1015","fyre-discard-vm-1016"]
def deleteMap=[:]
println "scriptOutput: ${proc7}"
def json = new groovy.json.JsonSlurper().parseText(proc7)
for (slave in slaveList)
{
println(slave);
if (json.find{it.data.name==slave}){ //This works as the properties are passed through as properties
id = json.find{it.data.name==slave}.key
deleteMap = deleteMap+[(slave):(id)]
// I would like to do something like this however I cannot figure out how to split my properties and pass them through in a way that works
/* if (json.find{it."$jsonName"==slave}){ SOMEHOW expand or split jsonName here
id = json.find{it."$jsonName"==slave}.key
deleteMap = deleteMap+[(slave):(id)] */
def jsonName="name"
id = json.find{it.data."${jsonName}"==slave}?.key
if (id) {
deleteMap = deleteMap+[(slave):(id)]
println "Match"
println (id)
println deleteMap;
}
}
else{
println"No"
}
}