Compare two JSON files and keep only matching using jq/bash - json

I have two files (I am copying just a small part of them as they are rather large):
_titles2.txt: (small sample)
{
"titleId": "0100000000010800"
}
{
"titleId": "010000000EEF0800"
}
{
"titleId": "0100000011D90800"
}
{
"titleId": "010000001260E800"
}
{
"titleId": "01000000160F6800"
}
{
"titleId": "010000100C4B8800"
}
titles.json (again just a small sample)
{
"1": {
"bannerUrl": null,
"category": null,
"description": null,
"developer": null,
"frontBoxArt": null,
"iconUrl": null,
"id": "0100000000000816",
"intro": null,
"isDemo": null,
"key": null,
"languages": null,
"name": null,
"nsuId": null,
"numberOfPlayers": null,
"publisher": null,
"rank": 34342,
"rating": null,
"ratingContent": null,
"region": null,
"regions": null,
"releaseDate": null,
"rightsId": null,
"screenshots": null,
"size": 0,
"version": null
},
"2": {
"bannerUrl": "https://img-eshop.cdn.nintendo.net/i/c42553b4fd0312c31e70ec7468c6c9bccd739f340152925b9600631f2d29f8b5.jpg",
"category": [
"Platformer",
"Action"
],
"description": "Explore incredible places far from the Mushroom Kingdom as you join Mario and his new ally Cappy on a massive, globe-trotting 3D adventure. Use amazing new abilities\u2014like the power to capture and control objects, animals, and enemies\u2014to collect Power Moons so you can power up the Odyssey airship and save Princess Peach from Bowser\u2019s wedding plans!\n\nThanks to heroic, hat-shaped Cappy, Mario\u2019s got new moves that\u2019ll make you rethink his traditional run-and-jump gameplay\u2014like cap jump, cap throw, and capture. Use captured cohorts such as enemies, objects, and animals to progress through the game and uncover loads of hidden collectibles. And if you feel like playing with a friend, just pass them a Joy-Con\u2122 controller! Player 1 controls Mario while Player 2 controls Cappy. This sandbox-style 3D Mario adventure\u2014the first since 1996\u2019s beloved Super Mario 64\u2122 and 2002\u2019s Nintendo GameCube\u2122 classic Super Mario Sunshine\u2122\u2014is packed with secrets and surprises, plus exciting new kingdoms to explore.",
"developer": null,
"frontBoxArt": null,
"iconUrl": "https://img-eshop.cdn.nintendo.net/i/ad4d31f664a1ce704f0219da2805f8459595bc3c01c3f04df2e32ba34a05b8c6.jpg",
"id": "0100000000010000",
"intro": "Embark on a cap-tivating, globe-trotting adventure",
"isDemo": false,
"key": null,
"language": "en",
"languages": [
"ja",
"en",
"es",
"fr",
"de",
"it",
"nl",
"ru",
"zh",
"zh"
],
"name": "Super Mario Odyssey\u2122",
"nsuId": 70010000001130,
"numberOfPlayers": 2,
"publisher": "Nintendo",
"rank": 2,
"rating": 10,
"ratingContent": [
"Cartoon Violence",
"Comic Mischief"
],
"region": "US",
"regions": [
"CO",
"AR",
"CL",
"PE",
"KR",
"HK",
"NZ",
"BE",
"CZ",
"DK",
"ES",
"FI",
"HU",
"NL",
"PL",
"RU",
"ZA",
"MX",
"CA",
"FR",
"DE",
"JP",
"AU",
"GB",
"US"
],
"releaseDate": 20171027,
"rightsId": "01000000000100000000000000000003",
"screenshots": [
"https://img-eshop.cdn.nintendo.net/i/c497547957d9dd3668e891aa97ff4899a3f40bd1bd430020f8cbdf673f02bdeb.jpg",
"https://img-eshop.cdn.nintendo.net/i/1839d571921e3fb19ef48da64c145cb8ce573b07d7390c6350f15291b3905048.jpg",
"https://img-eshop.cdn.nintendo.net/i/d0510e4804381287c64dc3ab374ae9273419e263e9a732e72af3b39cd70f2b5f.jpg",
"https://img-eshop.cdn.nintendo.net/i/ab713d841b0f0d9bbce38b589d75dd3bba2aef005418e59d3f0fd95389ae7016.jpg",
"https://img-eshop.cdn.nintendo.net/i/abcf9708cc28ef5b7ab412aa17fafe4ad181f0b957456ffd9b83de2561d9f62a.jpg",
"https://img-eshop.cdn.nintendo.net/i/7db70ecd883f94d935f65b9f4454b8151b6f8be7c4be95543e87488e48e5a6b9.jpg"
],
"size": 6026166272,
"version": 0
},
"3": {
"bannerUrl": null,
"category": null,
"description": null,
"developer": null,
"frontBoxArt": null,
"iconUrl": null,
"id": "0100000000010800",
"intro": null,
"isDemo": null,
"key": null,
"languages": null,
"name": null,
"nsuId": null,
"numberOfPlayers": null,
"publisher": null,
"rank": 34341,
"rating": null,
"ratingContent": null,
"region": null,
"regions": null,
"releaseDate": null,
"rightsId": null,
"screenshots": null,
"size": 0,
"version": 262144
},
"4": {
"bannerUrl": null,
"category": null,
"description": null,
"developer": null,
"frontBoxArt": null,
"iconUrl": null,
"id": "010000000E5EE000",
"intro": null,
"isDemo": null,
"key": null,
"languages": null,
"name": null,
"nsuId": null,
"numberOfPlayers": null,
"publisher": null,
"rank": 34340,
"rating": null,
"ratingContent": null,
"region": null,
"regions": null,
"releaseDate": null,
"rightsId": null,
"screenshots": null,
"size": 0,
"version": 0
},
"5": {
"bannerUrl": "https://img-eshop.cdn.nintendo.net/i/74dbbc2f5dd60e8c671a0c0a1ad18034e80e26375589765e90449ea4b5e15739.jpg",
"category": [
"Adventure",
"Action",
"Simulation"
],
"description": "Explore a darkened office complex and uncover the truth behind the horrifying events that have befallen its inhabitants.\nPlay as one of two characters with unique storylines, monster encounters, and gameplay challenges. \nNavigate a multi-story maze that grows scarier, harder, and more twisted as you struggle to escape the madness.",
"developer": null,
"frontBoxArt": null,
"iconUrl": "https://img-eshop.cdn.nintendo.net/i/4699a0d5b05a057a5d20c252d2d46a7eec5d41cfd46eb33e4e87b6247b3f7486.jpg",
"id": "010000000EEF0000",
"intro": "Shadows 2: Perfidia is a survival horror game inspired by classics like the Penumbra series and Layers of Fear.",
"isDemo": false,
"key": null,
"language": "en",
"languages": [
"en"
],
"name": "Shadows 2: Perfidia",
"nsuId": 70010000021900,
"numberOfPlayers": 1,
"publisher": "Ultimate Games",
"rank": 2963,
"rating": 17,
"ratingContent": [
"Blood and Gore",
"Intense Violence",
"Nudity",
"Sexual Content",
"Strong Language"
],
"region": "US",
"regions": [
"BE",
"CZ",
"DK",
"ES",
"FI",
"HU",
"NL",
"PL",
"RU",
"ZA",
"MX",
"CA",
"FR",
"DE",
"AU",
"GB",
"US"
],
"releaseDate": 20190806,
"rightsId": null,
"screenshots": [
"https://img-eshop.cdn.nintendo.net/i/a40b9ad80b4d6ab05c2ebc5dbf16484e4074a3a2b32b1ca15505dde5d56ebdd5.jpg",
"https://img-eshop.cdn.nintendo.net/i/4cd32eaf41ee287b4e9854646598c5b2feaf405d431977cf8f5002ef5a3fa428.jpg",
"https://img-eshop.cdn.nintendo.net/i/e2547655c002df78f573e1a79afd39dc70defce4d7e33fb3b68820fb5468d89d.jpg",
"https://img-eshop.cdn.nintendo.net/i/85d23d86660204f1f6fb14feece746e12860ce26944cff47ca407b53e8f2c686.jpg",
"https://img-eshop.cdn.nintendo.net/i/e499c7e25643ed0366cfdcff9c14da9cc5a528f841aba9be7188b531ef2fe219.jpg",
"https://img-eshop.cdn.nintendo.net/i/6b36b07122f2a4b8ac34df656159ce2e4020a6c19c06f8cdcafc221c9b4b5598.jpg"
],
"size": 2687500288,
"version": 0
},
Using jq, I want to test wether each objects 'titleId' in _titles2.txt exists in titles.json as 'id'. If it does exist, I would like for a third json file to be created with all the "matches" that were made.
I was able to do this with a single 'titleId' but can't seem to figure out how to do it for the full file (Other than doing a huge for loop and testing each individually)
Hoping someone could help with this! Thank you.
Thanks peak for the answer! Works flawlessly and searches in about 15 seconds!
I was hoping you could help me out modify this command though? I have the exact same task to do, with two files of the same format as the _titles2.txt (with the exception of the uppercase)
_titles3.txt
{
"TITLEID": "0100000000010000"
}
{
"TITLEID": "0100000000010800"
}
{
"TITLEID": "010000000E5EE000"
}
{
"TITLEID": "010000000EEF0000"
}
{
"TITLEID": "010000000EEF0800"
}
Just to recap - Using jq, I want to test wether each objects 'titleId' in _titles2.txt exists in _titles3.txt as 'TITTLEID'. If it does exist, I would like for a third json file to be created with all the "matches" that were made. (Same outcome, but I'm having issues getting the command to work as it is not one large object anymore - I also have no control over the data so I'm stuck manipulating with what I get)

If I understand the question properly, there is no need to call jq more than once, or to write a shell loop.
For example, if your goal is to produce a single JSON object, you could go with:
< titles.json jq --slurpfile titleIds _titles2.txt '
INDEX($titleIds[]; .titleId) as $dict
| with_entries( select($dict[.value.id]))
'
——
For the followup question: you could handle both cases by calling INDEX as follows:
INDEX($titleIds[]; .titleId//.TITLEID)

Related

How to add key to json file using powershell

i have a json file like this:
[
{
"DisplayName": "Title1",
"SignInName": null,
"RoleDefinitionName": "Name1",
"RoleDefinitionId": "1111",
"ObjectId": "0111",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
},
{
"DisplayName": "Title2",
"SignInName": null,
"RoleDefinitionName": "Name2",
"RoleDefinitionId": "1111",
"ObjectId": "02222",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
},
{
"DisplayName": "Title3",
"SignInName": null,
"RoleDefinitionName": "Name3",
"RoleDefinitionId": "33333",
"ObjectId": "03333",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
}
]
I need to add a KEY at a start with all this json as a VALUE of that key using powershell script so it would look like this:
{
"ManagedIdentity": [
{
"DisplayName": "Title1",
"SignInName": null,
"RoleDefinitionName": "Name1",
"RoleDefinitionId": "1111",
"ObjectId": "0111",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
},
{
"DisplayName": "Title2",
"SignInName": null,
"RoleDefinitionName": "Name2",
"RoleDefinitionId": "1111",
"ObjectId": "02222",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
},
{
"DisplayName": "Title3",
"SignInName": null,
"RoleDefinitionName": "Name3",
"RoleDefinitionId": "33333",
"ObjectId": "03333",
"ObjectType": "ServicePrincipal",
"CanDelegate": false,
"Description": null,
"ConditionVersion": null,
"Condition": null
}
]
}
I should do it inside one script block, and i am not sure how to figure this out. It is a ready json file that i need to append key to.
The script that gets a file is something like this:
Get-AzRoleAssignment -ObjectId 02222 | ConvertTo-Json
to this short script using pipes i need to append a solution to append the key to the file.

Linux JQ. How to extract data from specific ID Entry

Guy, long term looking at this board and learning a lot but now stuck with little issue. Im working with Linux shell script that reads json (no problem here). What Im trying to do is get value from entry that has specific Type.
By parsing a json with just jq -r '.', I get
{
"records": [
{
"id": 01,
"type": "SOA",
"name": "#",
"data": "1800",
"priority": null,
"port": null,
"ttl": 1800,
"weight": null,
"flags": null,
"tag": null
},
{
"id": 02,
"type": "A",
"name": "#",
"data": "test.com",
"priority": null,
"port": null,
"ttl": 1800,
"weight": null,
"flags": null,
"tag": null
}
],
"links": {},
"meta": {
"total": 2
}
}
Then, I use "jq -r '.records' " and get:
[
{
"id": 01,
"type": "SOA",
"name": "#",
"data": "1800",
"priority": null,
"port": null,
"ttl": 1800,
"weight": null,
"flags": null,
"tag": null
},
{
"id": 02,
"type": "A",
"name": "#",
"data": "test.com",
"priority": null,
"port": null,
"ttl": 1800,
"weight": null,
"flags": null,
"tag": null
}
]
What I need to do is get data value of the type A. Currently, we have type SOA and A, but I need to only get data from A.
I can use dummy way of "jq -r '.records[1].data'" and it gives me correct response of test.com, but I want a more dynamic way of searching for specific type (in this case "A") and then giving the data value.
Thanks guys!
Is the field called domain_records or just records?
Use select to match your criteria
jq -r '.records[] | select(.type == "A").data'
test.com
Demo

Is there a way to fetch needed information from JSON file in React Native

I am using a COVID-19 API (https://api.covidactnow.org/v2/counties.json?apiKey=) that records various information like number of cases and deaths in each county in USA. In my React Native app, I retrieved the user's location, and more specifically, the user's county, state and country. In this case, I have stored the user's county name in countyName. I'd like to fetch the specific cases and deaths from the JSON file depending on what is countyName is. I have a snippet of one county in the JSON file below. I was thinking I could go into the index of the array and in the actuals, and then fetch the cases and deaths.
[
{
"fips": "02013",
"country": "US",
"state": "AK",
"county": "Aleutians East Borough",
"level": "county",
"lat": null,
"locationId": "iso1:us#iso2:us-ak#fips:02013",
"long": null,
"population": 3337,
"metrics": {
"testPositivityRatio": null,
"testPositivityRatioDetails": {
"source": "other"
},
"caseDensity": 0,
"contactTracerCapacityRatio": null,
"infectionRate": 4.71887277063,
"infectionRateCI90": 1.1615979428900003,
"icuHeadroomRatio": null,
"icuHeadroomDetails": null,
"icuCapacityRatio": null,
"vaccinationsInitiatedRatio": null,
"vaccinationsCompletedRatio": 0.27509739286784535
},
"riskLevels": {
"overall": 0,
"testPositivityRatio": 4,
"caseDensity": 0,
"contactTracerCapacityRatio": 4,
"infectionRate": 3,
"icuHeadroomRatio": 4,
"icuCapacityRatio": 4
},
"actuals": {
"cases": 363,
"deaths": 2,
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null,
"typicalUsageRate": null
},
"icuBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null,
"typicalUsageRate": null
},
"newCases": 0,
"newDeaths": 0,
"vaccinesDistributed": null,
"vaccinationsInitiated": null,
"vaccinationsCompleted": 918,
"vaccinesAdministered": null,
"vaccinesAdministeredDemographics": null,
"vaccinationsInitiatedDemographics": null
},
"annotations": {
"cases": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"deaths": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": null,
"icuBeds": null,
"newCases": null,
"newDeaths": null,
"vaccinesDistributed": null,
"vaccinationsInitiated": null,
"vaccinationsCompleted": {
"sources": [
{
"type": "other",
"url": "https://covid.cdc.gov/covid-data-tracker/#county-view",
"name": "Centers for Disease Control and Prevention"
}
],
"anomalies": []
},
"vaccinesAdministered": null,
"testPositivityRatio": null,
"caseDensity": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"contactTracerCapacityRatio": null,
"infectionRate": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"infectionRateCI90": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"icuHeadroomRatio": null,
"icuCapacityRatio": null,
"vaccinationsInitiatedRatio": null,
"vaccinationsCompletedRatio": null
},
"lastUpdatedDate": "2021-04-26",
"url": "https://covidactnow.org/us/alaska-ak/county/aleutians_east_borough"
},
The response that you got from the API in JSON format is an array of objects.
To get the no of deaths and cases from the array of objects, you need to do the following:
const response= [
{
"fips": "02013",
"country": "US",
"state": "AK",
"county": "Aleutians East Borough",
"level": "county",
"lat": null,
"locationId": "iso1:us#iso2:us-ak#fips:02013",
"long": null,
"population": 3337,
"metrics": {
"testPositivityRatio": null,
"testPositivityRatioDetails": {
"source": "other"
},
"caseDensity": 0,
"contactTracerCapacityRatio": null,
"infectionRate": 4.71887277063,
"infectionRateCI90": 1.1615979428900003,
"icuHeadroomRatio": null,
"icuHeadroomDetails": null,
"icuCapacityRatio": null,
"vaccinationsInitiatedRatio": null,
"vaccinationsCompletedRatio": 0.27509739286784535
},
"riskLevels": {
"overall": 0,
"testPositivityRatio": 4,
"caseDensity": 0,
"contactTracerCapacityRatio": 4,
"infectionRate": 3,
"icuHeadroomRatio": 4,
"icuCapacityRatio": 4
},
"actuals": {
"cases": 363,
"deaths": 2,
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null,
"typicalUsageRate": null
},
"icuBeds": {
"capacity": null,
"currentUsageTotal": null,
"currentUsageCovid": null,
"typicalUsageRate": null
},
"newCases": 0,
"newDeaths": 0,
"vaccinesDistributed": null,
"vaccinationsInitiated": null,
"vaccinationsCompleted": 918,
"vaccinesAdministered": null,
"vaccinesAdministeredDemographics": null,
"vaccinationsInitiatedDemographics": null
},
"annotations": {
"cases": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"deaths": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"positiveTests": null,
"negativeTests": null,
"contactTracers": null,
"hospitalBeds": null,
"icuBeds": null,
"newCases": null,
"newDeaths": null,
"vaccinesDistributed": null,
"vaccinationsInitiated": null,
"vaccinationsCompleted": {
"sources": [
{
"type": "other",
"url": "https://covid.cdc.gov/covid-data-tracker/#county-view",
"name": "Centers for Disease Control and Prevention"
}
],
"anomalies": []
},
"vaccinesAdministered": null,
"testPositivityRatio": null,
"caseDensity": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"contactTracerCapacityRatio": null,
"infectionRate": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"infectionRateCI90": {
"sources": [
{
"type": "NYTimes",
"url": "https://github.com/nytimes/covid-19-data",
"name": "The New York Times"
}
],
"anomalies": []
},
"icuHeadroomRatio": null,
"icuCapacityRatio": null,
"vaccinationsInitiatedRatio": null,
"vaccinationsCompletedRatio": null
},
"lastUpdatedDate": "2021-04-26",
"url": "https://covidactnow.org/us/alaska-ak/county/aleutians_east_borough"
}
]
const enteredCountryName = "US";
//Getting the required country name from the array of objects using filter method
const countryArray = response.filter(item => item.country === enteredCountryName)
const noOfDeaths = countryArray[0].actuals.deaths;
const noOfCases = countryArray[0].actuals.cases;
console.log({noOfDeaths, noOfCases})
If you are only interested in a specific county, there is an endpoint for this in the API. Just query this, then there is no need to filter the fetched data further:
https://api.covidactnow.org/v2/county/{fips}.json?apiKey=YOUR_KEY_HERE

Search JSON file bash

I have following JSON file and would like to extract part of it:
{
"expand": "names,schema",
"issues": [
{
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
"fields": {
"aggregateprogress": {
"progress": 0,
"total": 0
},
"aggregatetimeestimate": null,
"aggregatetimeoriginalestimate": null,
"aggregatetimespent": null,
"assignee": {
"active": true,
"avatarUrls": {
"16x16": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=16",
"24x24": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=24",
"32x32": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=32",
"48x48": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=48"
},
"displayName": "user",
"emailAddress": "user#company.com",
"key": "user",
"name": "user",
"self": "https://jira.corp.company.com/rest/api/2/user?username=dvucanovic",
"timeZone": "Europe/Belgrade"
},
"components": [],
"created": "2018-03-06T21:24:41.000+0000",
"creator": {
"active": true,
"avatarUrls": {
"16x16": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=16",
"24x24": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=24",
"32x32": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=32",
"48x48": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=48"
},
"displayName": "user",
"emailAddress": "user#company.com",
"key": "user",
"name": "user",
"self": "https://jira.corp.company.com/rest/api/2/user?username=dvucanovic",
"timeZone": "Europe/Belgrade"
},
"customfield_10000": null,
"customfield_10001": null,
"customfield_10002": null,
"customfield_10004": "0|i00uta:",
"customfield_10005": null,
"customfield_10006": null,
"customfield_10100": null,
"customfield_10101": [],
"customfield_10102": null,
"customfield_10103": null,
"customfield_10107": {
"id": "10400",
"self": "https://jira.corp.company.com/rest/api/2/customFieldOption/10400",
"value": "Hentsu Internal"
},
"customfield_10108": null,
"customfield_10200": null,
"customfield_10201": "2018-03-06",
"customfield_10202": "2018-03-06",
"customfield_10203": null,
"customfield_10204": null,
"customfield_10205": null,
"customfield_10206": null,
"customfield_10300": "com.atlassian.servicedesk.plugins.approvals.internal.customfield.ApprovalsCFValue#5e6792fb",
"customfield_10301": null,
"customfield_10302": null,
"customfield_10600": null,
"customfield_10700": null,
"customfield_11000": null,
"customfield_11001": null,
"customfield_11002": null,
"customfield_11003": null,
"customfield_11004": null,
"customfield_11005": null,
"customfield_11006": null,
"customfield_11007": null,
"customfield_11008": null,
"customfield_11009": null,
"customfield_11010": null,
"customfield_11011": null,
"customfield_11012": null,
"customfield_11013": null,
"customfield_11014": null,
"customfield_11015": null,
"customfield_11016": null,
"customfield_11017": null,
"customfield_11018": null,
"customfield_11019": null,
"customfield_11100": null,
"customfield_11101": null,
"customfield_11102": null,
"description": null,
"duedate": null,
"environment": null,
"fixVersions": [],
"issuelinks": [],
"issuetype": {
"avatarId": 10318,
"description": "A task that needs to be done.",
"iconUrl": "https://jira.corp.company.com/secure/viewavatar?size=xsmall&avatarId=10318&avatarType=issuetype",
"id": "10100",
"name": "Task",
"self": "https://jira.corp.company.com/rest/api/2/issuetype/10100",
"subtask": false
},
"labels": [],
"lastViewed": "2018-03-06T21:31:34.315+0000",
"priority": {
"iconUrl": "https://jira.corp.company.com/images/icons/priorities/medium.svg",
"id": "3",
"name": "Medium",
"self": "https://jira.corp.company.com/rest/api/2/priority/3"
},
"progress": {
"progress": 0,
"total": 0
},
"project": {
"avatarUrls": {
"16x16": "https://jira.corp.company.com/secure/projectavatar?size=xsmall&pid=10001&avatarId=10201",
"24x24": "https://jira.corp.company.com/secure/projectavatar?size=small&pid=10001&avatarId=10201",
"32x32": "https://jira.corp.company.com/secure/projectavatar?size=medium&pid=10001&avatarId=10201",
"48x48": "https://jira.corp.company.com/secure/projectavatar?pid=10001&avatarId=10201"
},
"id": "10001",
"key": "TECH",
"name": "Technology",
"self": "https://jira.corp.company.com/rest/api/2/project/10001"
},
"reporter": {
"active": true,
"avatarUrls": {
"16x16": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=16",
"24x24": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=24",
"32x32": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=32",
"48x48": "https://secure.gravatar.com/avatar/5d92f3ce51d4a090cdcb9b77ee890989?d=mm&s=48"
},
"displayName": "user",
"emailAddress": "user#company.com",
"key": "user",
"name": "user",
"self": "https://jira.corp.company.com/rest/api/2/user?username=dvucanovic",
"timeZone": "Europe/Belgrade"
},
"resolution": null,
"resolutiondate": null,
"status": {
"description": "",
"iconUrl": "https://jira.corp.company.com/",
"id": "10000",
"name": "Backlog",
"self": "https://jira.corp.company.com/rest/api/2/status/10000",
"statusCategory": {
"colorName": "blue-gray",
"id": 2,
"key": "new",
"name": "To Do",
"self": "https://jira.corp.company.com/rest/api/2/statuscategory/2"
}
},
"subtasks": [
{
"fields": {
"issuetype": {
"avatarId": 10316,
"description": "The sub-task of the issue",
"iconUrl": "https://jira.corp.company.com/secure/viewavatar?size=xsmall&avatarId=10316&avatarType=issuetype",
"id": "10101",
"name": "Sub-task",
"self": "https://jira.corp.company.com/rest/api/2/issuetype/10101",
"subtask": true
},
"priority": {
"iconUrl": "https://jira.corp.company.com/images/icons/priorities/medium.svg",
"id": "3",
"name": "Medium",
"self": "https://jira.corp.company.com/rest/api/2/priority/3"
},
"status": {
"description": "",
"iconUrl": "https://jira.corp.company.com/",
"id": "10000",
"name": "Backlog",
"self": "https://jira.corp.company.com/rest/api/2/status/10000",
"statusCategory": {
"colorName": "blue-gray",
"id": 2,
"key": "new",
"name": "To Do",
"self": "https://jira.corp.company.com/rest/api/2/statuscategory/2"
}
},
"summary": "Disable user account in Local AD"
},
"id": "16916",
"key": "TECH-728",
"self": "https://jira.corp.company.com/rest/api/2/issue/16916"
}
],
"summary": "disable user mm",
"timeestimate": null,
"timeoriginalestimate": null,
"timespent": null,
"updated": "2018-03-06T21:27:22.000+0000",
"versions": [],
"votes": {
"hasVoted": false,
"self": "https://jira.corp.company.com/rest/api/2/issue/TECH-726/votes",
"votes": 0
},
"watches": {
"isWatching": true,
"self": "https://jira.corp.company.com/rest/api/2/issue/TECH-726/watchers",
"watchCount": 1
},
"workratio": -1
},
"id": "16914",
"key": "TECH-726",
"self": "https://jira.corp.company.com/rest/api/2/issue/16914"
}
],
"maxResults": 50,
"startAt": 0,
"total": 1
}
How to extract only part in subtasks section
(subtask:true) ?
tried with:
jq -r '.issues[] | .fields.issuetype.subtask' 1.json # and
jq -r '.subtasks[] |.fields.issuetype.subtask' 1.json
but always get false
jq -r '.subtasks[] | .fields.issuetype.subtask' 1.json
jq: error (at 1.json:231): Cannot iterate over null (null)
jq solution:
jq '.issues[].fields.subtasks[].fields | .issuetype.subtask, .summary' 1.json
The output:
true
"Disable user account in Local AD"
With respect to a best-practice mechanism to iterate over output in bash (assuming, here, that the subtask field will never contain a literal tab, and that summary will never contain a literal newline):
while IFS=$'\t' read -r subtask summary; do
echo "Got subtask $subtask and summary $summary"
done < <(jq -r '.issues[].fields.subtasks[].fields
| [.issuetype.subtask, .summary] | #tsv')
If you want to avoid those assumptions, you can do even better by using NUL delimiters, which will correctly handle all values which can potentially be stored in a variable in bash:
while IFS= read -r -d '' subtask && IFS= read -r -d '' summary; do
printf 'Got subtask %q and summary %q\n' "$subtask" "$summary"
done < <(jq -j '.issues[].fields.subtasks[].fields
| (.issuetype.subtask, "\u0000", .summary, "\u0000")')
Community Wiki since this answer is intended to address an issue observed in comments on the accepted answer, rather than addressing the original question as such.

How to loop through JSON in ruby

Below details is my shipment details. I want to loop through this JSON and get each checkpoint details.
How can I do this with Ruby
This is my controller:
#asd = AfterShip::V4::Tracking.get('ups', '1Z31Y1Y90490064644')
this is my view page where i get json data
= #asd.to_json`
This is the JSON:
{
"meta": {
"code": 200
},
"data": {
"tracking": {
"id": "560b87b38c9079f272e98dfc",
"created_at": "2015-09-30T06:56:51+00:00",
"updated_at": "2015-09-30T06:56:55+00:00",
"last_updated_at": "2015-09-30T06:56:55+00:00",
"tracking_number": "1Z31Y1Y90490064644",
"slug": "ups",
"active": false,
"android": [
],
"custom_fields": null,
"customer_name": null,
"delivery_time": 7,
"destination_country_iso3": "GBR",
"emails": [
"pu#l.com"
],
"expected_delivery": null,
"ios": [
],
"note": null,
"order_id": null,
"order_id_path": null,
"origin_country_iso3": "HKG",
"shipment_package_count": 1,
"shipment_pickup_date": "2015-08-24T16:00:00",
"shipment_delivery_date": "2015-09-01T14:22:00",
"shipment_type": "UPS SAVER",
"shipment_weight": 0.5,
"shipment_weight_unit": "kg",
"signed_by": "MANTON (RESIDENTIAL)",
"smses": [
],
"source": "api",
"tag": "Delivered",
"title": "1Z31Y1Y90490064644",
"tracked_count": 1,
"unique_token": "bkGcaTOJDe",
"checkpoints": [
{
"slug": "ups",
"city": null,
"created_at": "2015-09-30T06:56:55+00:00",
"location": "HK",
"country_name": "HK",
"message": "BILLING INFORMATION RECEIVED",
"country_iso3": "HKG",
"tag": "InfoReceived",
"checkpoint_time": "2015-08-25T23:05:47",
"coordinates": [
],
"state": null,
"zip": null
},
{
"slug": "ups",
"city": null,
"created_at": "2015-09-30T06:56:55+00:00",
"location": null,
"country_name": null,
"message": "YOUR PACKAGE WAS RELEASED BY THE CLEARING AGENCY.",
"country_iso3": null,
"tag": "InTransit",
"checkpoint_time": "2015-08-27T16:57:00",
"coordinates": [
],
"state": null,
"zip": null
},
{
"slug": "ups",
"city": null,
"created_at": "2015-09-30T06:56:55+00:00",
"location": null,
"country_name": null,
"message": "YOUR PACKAGE WAS RELEASED BY THE CLEARING AGENCY.",
"country_iso3": null,
"tag": "InTransit",
"checkpoint_time": "2015-08-27T17:07:00",
"coordinates": [
],
"state": null,
"zip": null
}
}
}
}
What you are getting here is an instance of Hash class (the response JSON is already parsed).
tracking = AfterShip::V4::Tracking.get('ups', '1Z31Y1Y90490064644')
tracking['data']['tracking']['id']
# => "560b87b38c9079f272e98dfc"