Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using jq to update objects within a JSON document if the value corresponding to a given key starts with a specified string

Tags:

json

bash

shell

jq

I have the given JSON and want to change the id value of all elements, which starts with test in the name element:

{
    "other-value": "some-id",
    "values": [
        {
            "name": "test-2017-12-01",
            "id": "1"

        },
        {
            "name": "othert",
            "id": "2"
        }

    ]
}

The following jq commands works jqplay

jq (.values[] | select(.name == "test-afs").id) |= "NEWID"

But when I try it with startswith it stops working, what am I missing? jqplay

(.values[] | select(.name | startswith("test")).id) |= "NEWID" 

jq: error (at :14): Invalid path expression near attempt to access element "id" of {"name":"test-afs","id":"id"} exit status 5

like image 574
manixx Avatar asked Jun 07 '17 10:06

manixx


People also ask

Can jq write JSON?

jq is an amazing little command line utility for working with JSON data. We've written before about how you can use jq to parse JSON on the command line, but in this post I want to talk about using jq to create JSON data from scratch or make changes to existing data.

What is a jq filter?

jq filters run on a stream of JSON data. The input to jq is parsed as a sequence of whitespace-separated JSON values which are passed through the provided filter one at a time. The output(s) of the filter are written to standard out, again as a sequence of whitespace-separated JSON data.

What is jq in curl?

jq is a program described as “ sed for JSON data": You can use it to slice and filter and map and transform structured data with the same ease that sed, awk, grep and friends let you play with text.

What is jq command in bash?

So, to implement bash shell scripts using REST APIs, you must know how to parse the response of REST API (that is, parse JSON data). Jq is a program developed to filter JSON data. You can consider Jq like sed, awk, or grep program but designed specifically for filtering JSON data.


2 Answers

You can also use map, like this:

jq '(.values)|=(map((if .name|startswith("test") then .id="NEWID"  else . end)))' file

Output:

{
  "other-value": "some-id",
  "values": [
    {
      "name": "test-2017-12-01",
      "id": "NEWID"
    },
    {
      "name": "othert",
      "id": "2"
    }
  ]
}
like image 124
hek2mgl Avatar answered Oct 20 '22 00:10

hek2mgl


Please note that since the release of jq 1.5, jq has been enhanced to support the query that previously failed. For example, using the current 'master' version:

jq -c '(.values[] | select(.name | startswith("test")).id) |= "NEWID"'
{"other-value":"some-id","values":[{"name":"test-2017-12-01","id":"NEWID"},{"name":"othert","id":"2"}]}

Using earlier versions of jq, if/then/else/end can be used in this type of situation as follows:

.values[] |= if .name | startswith("test") then .id = "NEWID" else . end

If using map, a minimalist expression would be:

.values |= map(if .name|startswith("test") then .id = "NEWID" else . end)
like image 45
peak Avatar answered Oct 19 '22 22:10

peak