Get an array of all value of a key - bash

I am new to bash and jq. I want an array of all value of a key.
i have tried something like this but it doesn't work
jobName=$(echo "$jobResult" | jq '. | to_entries[] | .value.name')
but it gave a string to me like this string
"Basement Parking Construction Site 1" "Basement Parking Construction Site 2"
Input
{
"1": {
"_status_code": 202,
"_status_message": "Accepted",
"id": 4120489,
"parent_id": 0,
"assigned_to_all": false,
"billable": false,
"active": true,
"type": "regular",
"has_children": false,
"billable_rate": 0,
"short_code": "",
"name": "Basement Parking Construction Site 1",
"last_modified": "2019-03-12T10:02:54+00:00",
"created": "2019-03-12T10:02:54+00:00",
"filtered_customfielditems": "",
"required_customfields": [],
"locations": [],
"project_id": 0
},
"2": {
"_status_code": 202,
"_status_message": "Accepted",
"id": 4120491,
"parent_id": 0,
"assigned_to_all": false,
"billable": false,
"active": true,
"type": "regular",
"has_children": false,
"billable_rate": 0,
"short_code": "",
"name": "Basement Parking Construction Site 2",
"last_modified": "2019-03-12T10:02:54+00:00",
"created": "I019-03-12T10:02:54+00:00",
"filtered_customfielditems": "",
"required_customfields": [],
"locations": [],
"project_id": 0
}
I want an array of all the value with key name
result
["Basement Parking Construction Site 1","Basement Parking Construction Site 2"]

One of many possible solutions:
[.[] | .name]
If you want to ensure the values in the resultant array are distinct, you could add the unique filter.
Creating a bash array
If your bash has readarray, you can read the "name" values into a bash array, a, as follows:
readarray a <<< $(jq '.[] | .name' so-to-bash-array.json)
If not, simply use a bash loop.
Depending on your requirements, you might want to use the -r command-line option of jq.

Related

How do i get id from json with jq?

i have json. How can I get the id whose attributes value is 0fda6bb8-4fc9-4463-9d26-af2d503cb19c ?
[
{
"id": "c3b1516d-5b2c-4838-b5eb-77d94d634832",
"versionId": "c3b1516d-5b2c-4838-b5eb-77d94d634832",
"name": "выписка маленькая заявка с лендинга ИБ",
"entityTypeName": "TestCases",
"projectId": "6dfe2ace-dd40-4e36-b66e-4a655a855a2f",
"sectionId": "bf7fbece-4fdf-466a-b041-2d830debc844",
"isAutomated": false,
"globalId": 264511,
"duration": 300,
"attributes": {
"1be40893-5dad-4b37-b70d-b830c4bd273f": "0fda6bb8-4fc9-4463-9d26-af2d503cb19c",
"f4b408ae-5418-4a8d-99d9-4a67cb34870b": "fa000fb2-375d-4eb5-901c-fb5df30785ad"
},
"createdById": "995b1f08-cc65-409c-aa1c-a16c82dabf1d",
"modifiedById": "995b1f08-cc65-409c-aa1c-a16c82dabf1d",
"createdDate": "2022-10-12T00:22:43.544Z",
"modifiedDate": "2022-10-12T00:22:43.544Z",
"state": "NeedsWork",
"priority": "Medium",
"isDeleted": false,
"tagNames": [
"master"
],
"iterations": []
},
{
"id": "ec423701-f2a8-4667-8459-939a6e079941",
"versionId": "0dfe176e-b172-47ae-8049-e6974086d497",
"name": "[iOS] СБПэй фичатоглы. Fts.SBPay.Settings выключен Fts.C2B.Settings.Subscriptions включен",
"entityTypeName": "TestCases",
"projectId": "6dfe2ace-dd40-4e36-b66e-4a655a855a2f",
"sectionId": "8626c9f5-a5aa-4584-bbca-e9cd60369a5e",
"isAutomated": false,
"globalId": 402437,
"duration": 300,
"attributes": {
"1be40893-5dad-4b37-b70d-b830c4bd273f": "b52bfc88-9b13-41e1-8b4c-098ebfa673e0",
"240b7589-9461-44dc-8b13-361132877c50": "cfd99bad-fb3f-43fe-be8a-cb745f2d4c78",
"6639eb1a-1335-44ec-ba8b-c3c52bff9e79": "ed3bc553-e873-472f-8dc1-7f2720ad457d",
"9ae36ef5-ca0e-4273-bb39-aedf289a119d": "6687017f-138b-4d75-91bd-c6465f1f5331",
"b862c3ee-55eb-486f-8125-a7a034d69340": "IBANK5-37207",
"f4b408ae-5418-4a8d-99d9-4a67cb34870b": "36dc55ac-359c-4312-9b1a-646ad5fd5aa9"
},
"createdById": "11a30c8b-73e2-4233-bbf5-7cc41556d3e0",
"modifiedById": "11a30c8b-73e2-4233-bbf5-7cc41556d3e0",
"createdDate": "2022-11-01T12:05:56.821Z",
"modifiedDate": "2022-11-02T14:16:55.246Z",
"state": "Ready",
"priority": "Medium",
"isDeleted": false,
"tagNames": [],
"iterations": []
}
]
I tried using
cat new2.xml | jq '.' | jq '.[] | select(."1be40893-5dad-4b37-b70d-b830c4bd273f" | index("0fda6bb8-4fc9-4463-9d26-af2d503cb19c")) | .[] .id'
but the search returns nothing
You could select on .attributes[] and display the id field only:
jq '.[] | select(.attributes[] == "0fda6bb8-4fc9-4463-9d26-af2d503cb19c").id'
Output:
"c3b1516d-5b2c-4838-b5eb-77d94d634832"
With the input given, you'd get the same result with the more specific:
jq '.[] | select(.attributes["1be40893-5dad-4b37-b70d-b830c4bd273f"] == "0fda6bb8-4fc9-4463-9d26-af2d503cb19c").id'
(because there's only one attribute Key with the Value "0fda6bb8-4fc9-4463-9d26-af2d503cb19c" in your example)

Nifi - Route the JSON based on the Array Name

I am new to Nifi, i hv a requirement where we get multiple JSON inputs with different Header Names. I have to parse the JSON and insert into different tables based on the Header value.
Not sure how to use RouteonContent processor or EvaluateJSON Path processor
Input 1
{
"Location": [
{
"country": "US",
"division": "Central",
"region": "Big South",
"locationID": 1015,
"location_name": "Hattiesburg, MS (XF)",
"location_type": "RETAIL",
"location_sub_type": "COS",
"store_type": "",
"planned_open_date": "",
"planned_close_date": "",
"actual_open_date": "2017-07-26",
"actual_close_date": "",
"new_store_flag": "",
"address1": "2100 Lincoln Road",
"address2": "",
"city": "Hattiesburg",
"state": "MS",
"zip": 39402,
"include_for_planning": "Y"
},
{
"country": "US",
"division": "Central",
"region": "Big South",
"locationID": 1028,
"location_name": "Laurel, MS",
"location_type": "RETAIL",
"location_sub_type": "COS",
"store_type": "",
"planned_open_date": "",
"planned_close_date": "",
"actual_open_date": "",
"actual_close_date": "",
"new_store_flag": "",
"address1": "1225 5th street",
"address2": "",
"city": "Laurel",
"state": "MS",
"zip": 39440,
"include_for_planning": "Y"
}
]
Input 2
{
"Item": [
{
"npi_code": "NEW",
"cifa_category": "XM",
"o9_category": "Accessories"
},
{
"npi_code": "NEW",
"cifa_category": "XM0",
"o9_category": "Accessories"
}
]
Use the website https://jsonpath.com/ to figure out the proper JSON expression. But what you could potentially do is use: if the array contains either $.npi_code then do X and if it contains $. country, then do Y

what's the simplest way to calculate the sum of values at the end of this jq command?

I see that jq can calculate addition as simply as jq 'map(.duration) | add' but I've got a more complex command and I can't figure out how to perform this add at the end of it.
I'm starting with data like this:
{
"object": "list",
"data": [
{
"id": "in_1HW85aFGUwFHXzvl8wJbW7V7",
"object": "invoice",
"account_country": "US",
"customer_name": "clientOne",
"date": 1601244686,
"livemode": true,
"metadata": {},
"paid": true,
"status": "paid",
"total": 49500
},
{
"id": "in_1HJlIZFGUwFHXzvlWqhegRkf",
"object": "invoice",
"account_country": "US",
"customer_name": "clientTwo",
"date": 1598297143,
"livemode": true,
"metadata": {},
"paid": true,
"status": "paid",
"total": 51000
},
{
"id": "in_1HJkg5FGUwFHXzvlYp2uC63C",
"object": "invoice",
"account_country": "US",
"customer_name": "clientThree",
"date": 1598294757,
"livemode": true,
"metadata": {},
"paid": true,
"status": "paid",
"total": 57000
},
{
"id": "in_1H8B0pFGUwFHXzvlU6nrOm6I",
"object": "invoice",
"account_country": "US",
"customer_name": "clientThree",
"date": 1595536051,
"livemode": true,
"metadata": {},
"paid": true,
"status": "paid",
"total": 20000
}
],
"has_more": true,
"url": "/v1/invoices"
}
and my jq command looks like:
cat example-data.json |
jq -C '[.data[]
| {invoice_id: .id, client: .customer_name, date: .date | strftime("%Y-%m-%d"), amount: .total, status: .status}
| .amount = "$" + (.amount/100|tostring)]
| sort_by(.date)'
which nicely gives me output like:
[
{
"invoice_id": "in_1H8B0pFGUwFHXzvlU6nrOm6I",
"client": "clientThree",
"date": "2020-07-23",
"amount": "$200",
"status": "paid"
},
{
"invoice_id": "in_1HJlIZFGUwFHXzvlWqhegRkf",
"client": "clientTwo",
"date": "2020-08-24",
"amount": "$510",
"status": "paid"
},
{
"invoice_id": "in_1HJkg5FGUwFHXzvlYp2uC63C",
"client": "clientThree",
"date": "2020-08-24",
"amount": "$570",
"status": "paid"
},
{
"invoice_id": "in_1HW85aFGUwFHXzvl8wJbW7V7",
"client": "clientOne",
"date": "2020-09-27",
"amount": "$495",
"status": "paid"
}
]
and I want to add a sum/total at the end of that, something like Total: $1775, so that the entire output would look like this:
[
{
"invoice_id": "in_1H8B0pFGUwFHXzvlU6nrOm6I",
"client": "clientThree",
"date": "2020-07-23",
"amount": "$200",
"status": "paid"
},
{
"invoice_id": "in_1HJlIZFGUwFHXzvlWqhegRkf",
"client": "clientTwo",
"date": "2020-08-24",
"amount": "$510",
"status": "paid"
},
{
"invoice_id": "in_1HJkg5FGUwFHXzvlYp2uC63C",
"client": "clientThree",
"date": "2020-08-24",
"amount": "$570",
"status": "paid"
},
{
"invoice_id": "in_1HW85aFGUwFHXzvl8wJbW7V7",
"client": "clientOne",
"date": "2020-09-27",
"amount": "$495",
"status": "paid"
}
]
Total: $1775
Is there a neat/tidy way to enhance this jq command to achieve this?
Or even, since I'm invoking this in a shell script, a dirty/ugly way with bash?
If any of your output is going to be raw, you need to pass -r; it'll just be ignored for data items that aren't strings.
Anyhow -- if you write (expr1, expr2), then your input will be passed through both expressions. Thus:
jq -Cr '
([.data[]
| {invoice_id: .id,
client: .customer_name,
date: .date | strftime("%Y-%m-%d"),
amount: .total,
status: .status}
| .amount = "$" + (.amount/100|tostring)
] | sort_by(.date)),
"Total: $\([.data[] | .total] | add | . / 100)"
'
In case you decide after all to emit valid JSON, here is a modular answer to the question that makes it easy to formulate alternative approaches, and which postpones the conversion of .amount to dollars for efficiency:
def todollar:
"$" + tostring;
def json:
[.data[]
| {invoice_id: .id,
client: .customer_name,
date: .date | strftime("%Y-%m-%d"),
amount: (.total/100),
status: .status} ]
| sort_by(.date) ;
json
| map_values(.amount |= todollar),
"Total: " + (map(.amount) | add | todollar)
As noted elsewhere, you will probably want to use the -r command-line option.

Laravel, appending an attribute to a returned json appends the entire object

I have 2 tables Customer(Parent) and jobCode(Child) with one to many relationships
I want to retrieve a child record but with one extra field from the parent (customerGuid) as well. My code:
$jobCodes=JobCode::all();
foreach ($jobCodes as $jobCode) {
$jobCode['customerGuid']=$jobCode->customer->guid;
// I also tried $jobCode->setAttribute('customerGuid',$jobCode->customer->guid);
}
return $jobCodes;
I was expecting just the parent's guid field to be appended to each jobCode object and returned. However the ENTIRE customer parent object is returned!
[{
"id": 137,
"customerId": 1,
"jobCode": "Journeyman Plumber",
"jobDescription": "Journeyman Plumber",
"created_at": null,
"updated_at": "2017-01-27 12:20:27",
"guid": "28f35e94-e483-11e6-98e9-e0db55883624",
"customerGuid": "8d48931d-dc61-11e6-8927-e0db55883624",
"customer": {
"id": 1,
"name": "ACME",
"address1": "",
"address2": "",
"city": "San Jose",
"zip": "",
"phone": "",
"fax": "",
"email": "",
"guid": "8d48931d-dc61-11e6-8927-e0db55883624",
"stateName": "California",
"created_at": null,
"updated_at": "2017-01-20 07:10:59"
}
}, {
"id": 138,
"customerId": 1,
"jobCode": "JRP PreFab",
"jobDescription": "JRP",
......,
Its because your return statement returns $jobCodes; which is the entire table you retrieve here: $jobCodes=JobCode::all();
try putting this inside your loop
echo '$jobCode' to see what is the output every time it loops
Reaching for the relationship customer on $jobCode you automatically lazy load the relationship object, which is stored in $jobCode->customer attribute.
Try this instead just returning the collection:
// return $jobCodes;
return $jobCodes->map(function($jobCode){
$jobCode = $jobCode->toArray();
unset($jobCode['customer']);
return $jobCode;
});

Merging multiple json arrays in the same file

I'm currently downloading a ton of jira issues to generate a report. Currently the 'full data' file has a ton of individual records like this:
{
"key": "645",
"type": "Bug",
"typeid": "1",
"status": "Closed",
"summary": "Crash when saving document",
"closedDate": "2014-10-03T09:01:23.000+0200",
"flag": null,
"fixVersionID": "123",
"fixVersionName": "2.7"
}
However, because I'm downloading multiple versions and appending to the same file I end up with this kind of structure.
[
{
"key": "645",
"type": "Bug",
"typeid": "1",
"status": "Closed",
"summary": "Crash when saving document",
"closedDate": "2014-10-03T09:01:23.000+0200",
"flag": null,
"fixVersionID": "123",
"fixVersionName": "2.7"
}
]
[
{
"key": "552",
"type": "Bug",
"typeid": "1",
"status": "Closed",
"summary": "Graphical Issue",
"closedDate": "2014-10-13T09:01:23.000+0200",
"flag": null,
"fixVersionID": "456",
"fixVersionName": "2.8"
}
]
What I want to do is to count the number of records with a specific date and then doing the same looping through a starting date to an end date using jq
But, I can't figure out how to:
Flatten the records so that they are one array not two
Strip the T09:01:23.000+0200 from the closedDate value
Count the number of objects with a specific date value such as 2014-10-13
You have multiple independent inputs. To be able to combine them in any meaningful way, you'll have to slurp up the input. The inputs will be treated as an array of the inputs. Then you could combine them into a single array by adding them.
Since the dates are all in a certain fixed format, you can take substrings of the dates.
"2014-10-13T09:01:23.000+0200"[:10] -> "2014-10-13"
Given that, you can then filter by the date you want and count using the length filter.
add | map(select(.closedDate[:10]=="2014-10-13")) | length
e.g.,
$ cat input.json
[
{
"key": "645",
"type": "Bug",
"typeid": "1",
"status": "Closed",
"summary": "Crash when saving document",
"closedDate": "2014-10-03T09:01:23.000+0200",
"flag": null,
"fixVersionID": "123",
"fixVersionName": "2.7"
}
]
[
{
"key": "552",
"type": "Bug",
"typeid": "1",
"status": "Closed",
"summary": "Graphical Issue",
"closedDate": "2014-10-13T09:01:23.000+0200",
"flag": null,
"fixVersionID": "456",
"fixVersionName": "2.8"
}
]
$ jq -s 'add | map(select(.closedDate[:10]=="2014-10-13")) | length' input.json
1
For question 1 and 2:
$ echo -e "[\n$(sed '/^[][]$/d;/closedDate/s/\(T[^"]*\)//g' json)\n]" > flat-json
To count the number for special day:
$ grep "closedDate" flat-json | grep "2014-10-13" | wc -l

Resources