11

I'm trying to use jq in order to change a child's value. For instance, I want to change the value of "test2" from ["yo", "bye"] to ["hi"].

{
   "title": "hello",
   "body": {
       "test1": 123,
       "test2": [
           "yo",
           "bye"  
       ]
   }
}

So far I could only change values of keys that are childs of the root. I can't figure out how to take this and go to .body.test2 instead of title:

cat test.conf | jq 'to_entries | map(if .key == "title" then . + {"value":"hello world"} else . end) | from_entries' > test2.conf
3
  • Would jq '{ body: (.body + { test2: ["hi"] }) }' do it?
    – dhag
    Dec 9, 2015 at 18:17
  • 3
    jq '.body.test2 = ["hi"]' will do it Dec 9, 2015 at 18:18
  • 3
    @glennjackman Just posted your comment as a community answer.
    – Delgan
    Jul 12, 2016 at 12:24

2 Answers 2

20

(Posting @glennjackman comment as a community answer to prevent system from autodeleting the question)

jq '.body.test2 = ["hi"]' will do it

0

The command

jq '.body.test2 = ["hi"]' test.conf >test2.conf

... would do it, but assuming you may want to have better control over the operation without having to hard-code the test2 key name and the text that you're adding:

printf '%s\n' "line 1" "line 2" "line 3" |
jq -SR . |
jq --arg section test2 '.body[$section] = [inputs]' test.conf - >test2.conf

This takes arbitrary lines of text (three lines in the example, but in theory, you would be able to cat a text document here or pass one directly as an argument to the following jq command) and converts these into separate JSON strings using jq -SR .. The pipeline then passes them to a second jq invocation that inserts them as an array under the correct section under the body key.

Using - as the second input filename with the final jq invocation causes the utility to insert the JSON strings from the standard input stream in place of inputs in the jq expression.

Given the document in the question, the above pipeline would produce the following JSON document in test2.conf:

{
  "title": "hello",
  "body": {
    "test1": 123,
    "test2": [
      "line 1",
      "line 2",
      "line 3"
    ]
  }
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .