How to pass String as a Property in Groovy. Multi-level JSON - java
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"
}
}
Related
Filter nested json data using jsonpath as in example
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"}]}
Rest-assured. get value from another value
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
how to calculate total value for the below JSON value U.O.M Wise in Java
how to calculate total value for the below JSON value U.O.M Wise in Java? sequence can be vary. We cannot expect number of uoms and sequence of results. i have created hashset and made unique uom. { value=100 uom=kg }, { value=200 uom=kg }, { value=100 uom=lt }, { value=100 uom=ab }, { value=100 uom=lt } Please provide some code ref
This is not valid JSON as it uses = as key\value separator (change to something like this and use tools like JSONLint to validate): [{ "value": "100", "uom": "kg" }, { "value": "200", "uom": "kg" }, { "value": "100", "uom": "lt" }, { "value": "100", "uom": "ab" }, { "value": "100", "uom": "lt" } ] Even having this structure you can parse it into a collection of touples (value, uom) and then just sum everything having same uom For example you can use this: javax.json.JsonArray body = Json.createReader(new StringReader(YOUR_JSON_STRING)).readArray(); and read a JSON to array of touples
mongodb query to find value in json
I started working with MongoDB. I prepared some basic training JSON: { "header": { "Hotel": { "data": [ { "name": "Hilton", "Id": "1231213421" } ] }, "standard": "5", "priceStage": "4" }, "data": { "http": { "strean": {} } } } and I wrote a query like this: db.hotel.find( "data": { Id: "1231213421"}) Why query does not return anything?
You're trying to match on an element within an array and you don't need to match on the entire array. So,something like the following will work: db.hotel.find({"header.Hotel.data": {"$elemMatch": {"Id": "1231213421"}}} );
Java: Properties file as JSON in Android
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?