I have a JSON structure like this:
{
"misc": {
"color": "blue",
"id": "yyyy-12345",
"birthdate": "2020-12-25",
"tools": [
{
"type": "power",
"name": "hammer"
},
{
"type": "manual",
"name": "grinder"
}
]
},
"people": [
{
"name": "bob",
"profession": "analyst",
"clients": [
{
"name": "alice",
"instance": "3",
"stringA": "prefix1/suffix-stuff"
},
{
"name": "richard",
"instance": "2",
"stringA": "prefix1/suffix-stuff-lkasjdlflsd",
"stringB": "prefix2/suffix-stuff-lllaksjllsdkf",
"stringC": "prefix2/suffix-stuff-jhfhklasldj"
},
{
"name": "melanie",
"instance": "0",
"stringA": "prefix1/suffix-stuff-lkalalajskljlklj",
"stringB": "prefix2/suffix-stuff-aljksdljsd"
}
]
},
{
"name": "sarah",
"profession": "developer",
"clients": [
{
"name": "george",
"instance": "0",
"stringA": "prefix1/suffix-stuff-xx-klasjdlk",
"stringB": "prefix2/suffix-stuff-yy-lkajsldf",
"stringC": "prefix3/suffix-stuff-lkklkl-lkasjdl"
},
{
"name": "anna",
"instance": "4",
"stringA": "prefix1/suffix-stuff-aa-lkadslkjjj",
"stringB": "prefix3/suffix-stuff-bb-lkasdjfl",
"stringC": "prefix2/suffix-stuff-cc-lkasjdf"
},
{
"name": "michael",
"instance": "0",
"stringA": "prefix1/suffix-stuff-ttlkajlksdfsd",
"stringB": "prefix2/suffix-stuff-rrklajsdlf",
"stringC": "prefix3/suffix-stuff-lkljlkjxx"
}
]
}
]
}
This is obviously a contrived example but it exactly matches my JSON structure.
My goal is to modify values for "stringA" and "stringB" but only for "people" with name == "bob" and only for "clients" with "instance" != "0".
I’ve read dozens of stackoverflow posts and other google search results, and I’ve tried dozens (maybe 100’s) of variations of jq commands but no luck–not even close. I’ve tried ‘..’ and walk, and various recursive functions that others have written (written prior to the availability of ‘..’ and walk, I think). My difficulty seems to be related to needing the entire JSON printed out but with conditional changes based on .people[].name and .people[].clients[].instance.
I really have no idea how this works, I guess.
If I run the above JSON data through a command such as
jq --arg name bob --arg prefix newprefix 'some-mysterious-jq-statements'
I want the output to be this:
{
"misc": {
"color": "blue",
"id": "yyyy-12345",
"birthdate": "2020-12-25",
"tools": [
{
"type": "power",
"name": "hammer"
},
{
"type": "manual",
"name": "grinder"
}
]
},
"people": [
{
"name": "bob",
"profession": "analyst",
"clients": [
{
"name": "alice",
"instance": "3",
"stringA": "newprefix/suffix-stuff-xyz-aksdjf"
},
{
"name": "richard",
"instance": "2",
"stringA": "newprefix/suffix-stuff-lkasjdlflsd",
"stringB": "newprefix/suffix-stuff-lllaksjllsdkf",
"stringC": "prefix3/suffix-stuff-jhfhklasldj"
},
{
"name": "melanie",
"instance": "0",
"stringA": "prefix1/suffix-stuff-lkalalajskljlklj",
"stringB": "prefix2/suffix-stuff-aljksdljsd"
}
]
},
{
"name": "sarah",
"profession": "developer",
"clients": [
{
"name": "george",
"instance": "0",
"stringA": "prefix1/suffix-stuff-xx-klasjdlk",
"stringB": "prefix2/suffix-stuff-yy-lkajsldf",
"stringC": "prefix3/suffix-stuff-lkklkl-lkasjdl"
},
{
"name": "anna",
"instance": "4",
"stringA": "prefix1/suffix-stuff-aa-lkadslkjjj",
"stringB": "prefix3/suffix-stuff-bb-lkasdjfl",
"stringC": "prefix2/suffix-stuff-cc-lkasjdf"
},
{
"name": "michael",
"instance": "0",
"stringA": "prefix1/suffix-stuff-ttlkajlksdfsd",
"stringB": "prefix2/suffix-stuff-rrklajsdlf",
"stringC": "prefix3/suffix-stuff-lkljlkjxx"
}
]
}
]
}
Notice that the person "bob" has had modifications to the values for stringA and stringB for two of his clients, "alice" and "richard". Nothing else has changed.
Thank you for your time and assistance! 🙂
2
Answers
Traverse to the desired locations using
select
to filter (I added// empty
to ignore fields producingnull
), then update|=
to your desired value usingsub
for a regex substitution.Demo
The following has the advantage of being portable, e.g. it works with jaq as well as jq: