Preparing JSON array of Objects from multiple array list - json

I am very new to the Groovy scripts and would like to build a JSON output from the below JSON input. Kindly help!
My JSON input looks like this:
{
"id":"1222",
"storageNode": {
"uuid": "22255566336",
"properties": {
"BuinessUnit": [
"Light",
"Fan",
"Watch"
],
"Contact": [
"abc#gmail.com",
"fhh#gmail.com"
],
"Location": [
"Banglore",
"Surat",
"Pune"
]
}
}
}
Expected Output:
[
{
"BuinessUnit": "Light",
"Contact": "abc#gmail.com",
"Location": "Banglore"
},
{
"BuinessUnit": "Fan",
"Contact": "fhh#gmail.com",
"Location": "Surat"
},
{
"BuinessUnit": "Watch",
"Contact": "",
"Location": "Pune"
}
]
Please note that in case any array is not matching the value count that will always be the last one and in that case, a blank value ("") has to be populated. The "BusinessUnit" object can be referred for array size validation.
My code looks like this:
import com.sap.gateway.ip.core.customdev.util.Message;
import java.util.HashMap;
import groovy.json.*;
def Message processData(Message message) {
//Body
def body = message.getBody(String.class);
def jsonSlurper = new JsonSlurper()
def list = jsonSlurper.parseText(body)
String temp
def BU = list.storageNode.properties.get("BusinessUnit")
def builder = new JsonBuilder(
BU.collect {
[
BusinessUnit: it
]
}
)
message.setBody(builder.toPrettyString())
return message
}
It is only returning this:
[
{
"BusinessUnit": "Light"
},
{
"BusinessUnit": "Fan"
},
{
"BusinessUnit": "Watch"
}
]
Now how will I add other parts to it? Please help!

I have come up with the following solution that converts source JSON string to the target JSON string:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def json = '''
{
"id":"1222",
"storageNode": {
"uuid": "22255566336",
"properties": {
"BusinessUnit": [
"Light",
"Fan",
"Watch"
],
"Contact": [
"abc#gmail.com",
"fhh#gmail.com"
],
"Location": [
"Banglore",
"Surat",
"Pune"
]
}
}
}
'''
println convert(json)
String convert(String json) {
def list = new JsonSlurper().parseText(json)
List<String> units = list.storageNode.properties.BusinessUnit
List<String> contacts = list.storageNode.properties.Contact
List<String> locations = list.storageNode.properties.Location
def result = []
units.eachWithIndex { unit, int index ->
result << [
BusinessUnit: unit,
Contact : contacts.size() > index ? contacts[index] : '',
Location : locations.size() > index ? locations[index] : '',
]
}
return new JsonBuilder(result).toPrettyString()
}
I've omitted the logic of getting string from the message and packaging transformed JSON into message.
I hope it will help you to move forward. Please let me know if you need further assistance here.

You can use the built-in Groovy facilities, like transpose():
import groovy.json.*
def json = new JsonSlurper().parseText '''{ "id":"1222", "storageNode": { "uuid": "22255566336", "properties": {
"BuinessUnit": [ "Light", "Fan", "Watch" ],
"Contact": [ "abc#gmail.com", "fhh#gmail.com" ],
"Location": [ "Banglore", "Surat", "Pune" ] } } }'''
def names = json.storageNode.properties*.key
def values = json.storageNode.properties*.value
int maxSize = values*.size().max()
// pad lists with trainiling spaces
values.each{ v -> ( maxSize - v.size() ).times{ v << '' } }
def result = values.transpose().collect{ tuple -> [ names, tuple ].transpose().collectEntries{ it } }
assert result.toString() == '[[BuinessUnit:Light, Contact:abc#gmail.com, Location:Banglore], [BuinessUnit:Fan, Contact:fhh#gmail.com, Location:Surat], [BuinessUnit:Watch, Contact:, Location:Pune]]'
This piece of code can process everything under storageNode.properties.

Related

Looping through groovy object(List) using each{it} and pass the the elements into a json payload in Jenkins

I have a list containing the name of workspaces in groovy Jenkinsfile. I wrote an each() loop to iterate through the list and use the names in the endpoint below to get the workspace ID from the api response.
def getWorkspaceId() {
def result = []
Listworkspace.each{
def response = httpRequest(
customHeaders: [
[ name: "Authorization", value: "Bearer " + env.BEARER_TOKEN ],
[ name: "Content-Type", value: "application/vnd.api+json" ]
],
url: "https://app.terraform.io/api/v2/organizations/${TF_ORGNAME}/workspaces/$it
)
def data = new JsonSlurper().parseText(response.content)
println ("Workspace Id: " + data.data.id)
result << data.data.id
}
return result
}
After getting the IDs, I want to pass them as part of a json payload.
def buildPayload() {
def workspaceID = new JsonSlurper().parseText(getWorkspaceId())
workspaceID.each{
def payload = """
{
"data": {
"attributes": {
"is-destroy":false,
"message":
},
"type":"runs",
"relationships": {
"workspace": {
"data": [
{"id": "$it", "type": "workspaces"}
]
}
}
}
}
}
"""
return payload
}
Is there a way I can iterate through the list of IDs returned and append each json object for the key "data" after iteration. See the code below
"relationships": {
"workspace": {
"data": [
{"id": "id1", "type": "workspaces"},
{"id": "id2", "type": "workspaces"},
{"id": "id3", "type": "workspaces"}
]
When making the api call, it throws a 400 Bad request error. I tried to print the payload and I found out it attaches the whole list of IDs to the payload.
Any suggestion will be greatly appreciated. Thank you.
def buildPayload() {
def workspaceID = new JsonSlurper().parseText(getWorkspaceId())
workspaceID.each{
def payload = """
{
"data": {
"attributes": {
"is-destroy":false,
"message":
},
"type":"runs",
"relationships": {
"workspace": {
"data": [
[id1, id2, id3]
]
}
}
}
}
}
"""
return payload
}
I'd recommend using the JsonOutput class to make your life easier. In essence, as long as your getWorkspaceId() method is returning a list of ids, you can do something like this:
import groovy.json.JsonOutput
def buildPayload(def ids) {
def payload = [
data: [
attributes: [
"is-destroy": false,
"message" : "",
],
type: "runs",
relationships: [
workspace: [
data: ids.collect {
return [id: it, type: "workspaces"]
}
]
]
]
]
return JsonOutput.toJson(payload)
}
This will take each id in your ids list and build a map where each id is identified by its number and the type: workspaces key pair. This is all then included in the larger payload.

How to get the All index values in Groovy JSON xpath

Please find the attached Groovy code which I am using to get the particular filed from the response body.
Query 1 :
It is retrieving the results when the I am using the correct Index value like if the data.RenewalDetails[o], will give output as Value 1 and if the data.RenewalDetails[1], output as Value 2.
But in my real case, I will never know about number of blocks in the response, so I want to get all the values that are satisficing the condition, I tried data.RenewalDetails[*] but it is not working. Can you please help ?
Query 2:
Apart from the above condition, I want to add one more filter, where "FamilyCode": "PREMIUM" in the Itemdetails, Can you help on the same ?
def BoundId = new groovy.json.JsonSlurper().parseText('{"data":{"RenewalDetails":[{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value1","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]},{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value2","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]}]},"warnings":[{"code":"xxxx","detail":"xxxxxxxx","title":"xxxxxxxx"}]}')
.data.RenewalDetails[0].Itemdetails.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33
}?.BoundId
println "Hello " + BoundId
Something like this:
def txt = '''\
{
"data": {
"RenewalDetails": [
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value1",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
},
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value2",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
}
]
},
"warnings": [
{
"code": "xxxx",
"detail": "xxxxxxxx",
"title": "xxxxxxxx"
}
]
}'''
def json = new groovy.json.JsonSlurper().parseText txt
List<String> BoundIds = json.data.RenewalDetails.Itemdetails*.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.size() == 33 && itemDetail.FamilyCode == 'PREMIUM'
}?.BoundId
assert BoundIds.toString() == '[Value1, Value2]'
Note, that you will get the BoundIds as a List
If you amend your code like this:
def json = new groovy.json.JsonSlurper().parse(prev.getResponseData()
you would be able to access the number of returned items as:
def size = json.data.RenewalDetails.size()
as RenewalDetails represents a List
Just add as many queries you want using Groovy's && operator:
find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33 &&
itemDetail.FamilyCode.equals('PREMIUM')
}
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

Groovy script to compare 2 JSON array objects

I am trying to find the best way to compare 2 JSON Array objects using Groovy script.
JSON Obj1 =
{
"PO":
[
{
"OrderNumber": "12345",
"Location": "US",
}
{
"OrderNumber": "11223",
"Location": "US",
}
]
}
JSON Obj2 = {
"ResultPO":
[
{
"OrderNumber": "12345_00001",
"Location": "US",
"Customer": "ABC"
}
{
"OrderNumber": "98765_00002",
"Location": "US",
"Customer": "XYZ"
}
]
}
I need to return the JSON Output as below after finding the obj1 value in obj2 where OrderNumber is key identifier.
{
"ResultPO":
[
{
"OrderNumber": "12345_00001",
"Location": "US",
"Customer": "ABC"
}
]
}
Below is the sample code I have tried using JsonSlurper and findall but not able to get desired outcome.
def builder
def filterJson
filterJson = Obj2.findAll(){ it.OrderNumber.substring(0,4) == Obj1.OrderNumber.text()}
builder = new JsonBuilder(filterJson)
Try this one:
class OrderFilterSpec extends Specification {
def str1 = """{"PO":[
{"OrderNumber": "12345","Location": "US"},
{"OrderNumber": "11223","Location": "US"}
]}"""
def str2 = """{"ResultPO":[
{"OrderNumber": "12345_00001","Location": "US","Customer": "ABC"},
{"OrderNumber": "98765_00002","Location": "US","Customer": "XYZ"}
]}"""
def slurper = new JsonSlurper()
def buildResult(String first, String second) {
def (parsed1, parsed2) = [slurper.parseText(first), slurper.parseText(second)]
def filteredOrders = parsed2.ResultPO.findAll {
it.OrderNumber[0..4] in parsed1.PO.collect { it.OrderNumber }
}
return [ResultPO: filteredOrders]
}
def 'test order filtering'() {
expect:
buildResult(str1, str2) == [ResultPO: [[OrderNumber: '12345_00001', Location: 'US', Customer: 'ABC']]]
}
}

Can I combine Json.Builder with JsonOutput in groovy? CSV to JSON

I have to parse csv file (with some modifications) to json in groovy.When I'm trying to execute this code i have a problem with spliting some values.
Content of csv file:
TestKey;Finished;user;status
RWS.PT.001;2020-07-20T23:01:21+02:00;admin;PASS;
RWS.PT.002;2020-07-20T23:02:21+02:00;admin;PASS;
my code in groovy:
import groovy.json.*
def builder = new groovy.json.JsonBuilder()
def root = builder {
testExecutionKey 'DEMO-303'
info (
user: 'admin')
tests 'rows':'ghgh','uuuuu'
}
print JsonOutput.prettyPrint(JsonOutput.toJson(root))
def csvfile = new File('C:/temp/raportTest.csv').readLines()
def keys = csvfile[0].split(';')
def rows = csvfile[1..-1].collect { line ->
def i = 0, vals = line.split(';')
keys.inject([:]) { map, key -> map << ["$key": vals[i++]] }
}
print JsonOutput.prettyPrint(JsonOutput.toJson(rows))
my target file should looks like this:
{
"testExecutionKey": "DEMO-303",
"info" : {
"user" : "admin"
},
"tests" : [
{
"testKey" : "RWS.PT.001",
"finished" : "2020-07-20T23:01:21+02:00",
"status" : "PASS"
},
{
"testKey" : "RWS.PT.002",
"finished" : "2020-07-20T23:01:21+02:00",
"status" : "PASS"
}
]
}
Now I have:
{
"testExecutionKey": "DEMO-303",
"info": {
"user": "admin"
},
"tests": [
{
"rows": "ghgh"
},
"uuuuu"
]
}[
{
"TestKey": "RWS.PT.001",
"Finished": "2020-07-20T23:01:21+02:00",
"user": "admin",
"status": "PASS"
},
{
"TestKey": "RWS.PT.002",
"Finished": "2020-07-20T23:02:21+02:00",
"user": "admin",
"status": "PASS"
}
]
How can I input code from def rows (from JsonOutput) into JsonBuilder (instead of "rows": "ghgh").
Please help!
You over-engineered it a bit. You actually don't have to combine anything, just use the JsonBuilder and some Groovy magic:
import groovy.json.*
def kindaFile = '''
TestKey;Finished;user;status
RWS.PT.001;2020-07-20T23:01:21+02:00;admin;PASS;
RWS.PT.002;2020-07-20T23:02:21+02:00;admin;PASS;
'''.trim()
def keys
def testList = []
//parse CSV
kindaFile.splitEachLine( /;/ ){ parts ->
if( !keys )
keys = parts
else{
def test = [:]
parts.eachWithIndex{ val, ix -> test[ keys[ ix ] ] = val }
testList << test
}
}
def builder = new JsonBuilder()
def root = builder {
testExecutionKey 'DEMO-303'
info user: 'admin'
tests testList
}
println JsonOutput.prettyPrint(JsonOutput.toJson(root))
prints
{
"testExecutionKey": "DEMO-303",
"info": {
"user": "admin"
},
"tests": [
{
"TestKey": "RWS.PT.001",
"Finished": "2020-07-20T23:01:21+02:00",
"user": "admin",
"status": "PASS"
},
{
"TestKey": "RWS.PT.002",
"Finished": "2020-07-20T23:02:21+02:00",
"user": "admin",
"status": "PASS"
}
]
}

Groovy: How to parse the json specific key's value into list/array

I am new to groovy and trying
1) from the output of prettyPrint(toJson()), I am trying to get a list of values from a specific key inside an json array using groovy. Using the below JSON output from prettyPrint example below, I am trying to create a list which consists only the values of the name key.
My Code:
def string1 = jiraGetIssueTransitions(idOrKey: jira_id)
echo prettyPrint(toJson(string1.data))
def pretty = prettyPrint(toJson(string1.data))
def valid_strings = readJSON text: "${pretty}"
echo "valid_strings.name : ${valid_strings.name}"
Output of prettyPrint(toJson(string1.data))is below JSON:
{
"expand": "places",
"places": [
{
"id": 1,
"name": "Bulbasaur",
"type": {
"grass",
"poison"
}
},
{
"id": 2,
"name": "Ivysaur",
"type": {
"grass",
"poison"
}
}
}
Expected result
valid_strings.name : ["Bulbasaur", "Ivysaur"]
Current output
valid_strings.name : null
The pretty printed JSON content is invalid.
If the JSON is valid, then names can be accessed as follows:
import groovy.json.JsonSlurper
def text = """
{
"expand": "places",
"places": [{
"id": 1,
"name": "Bulbasaur",
"type": [
"grass",
"poison"
]
},
{
"id": 2,
"name": "Ivysaur",
"type": [
"grass",
"poison"
]
}
]
}
"""
def json = new JsonSlurper().parseText(text)
println(json.places*.name)
Basically, use spray the attribute lookup (i.e., *.name) on the appropriate object (i.e., json.places).
I've used something similar to print out elements within the response in ReadyAPI
import groovy.json.*
import groovy.util.*
def json='[
{ "message" : "Success",
"bookings" : [
{ "bookingId" : 60002172,
"bookingDate" : "1900-01-01T00:00:00" },
{ "bookingId" : 59935582,
"bookingDate" : "1900-01-01" },
{ "bookingId" : 53184048,
"bookingDate" : "2019-01-15",
"testId" : "12803798123",
"overallScore" : "PASS" },
{ "bookingId" : 53183765,
"bookingDate" : "2019-01-15T13:45:00" },
{ "bookingId" : 52783312,
"bookingDate" : "1900-01-01" }
]
}
]
def response = context.expand( json )
def parsedjson = new groovy.json.JsonSlurper().parseText(response)
log.info parsedjson
log.info " Count of records returned: " + parsedjson.size()
log.info " List of bookingIDs in this response: " + parsedjson.bookings*.bookingId