13

I'm trying to generate a json file within bash. I installed jq, hoping that it would help me generate and append json.

For example, I want to generate a json in this format:

{
  "Project": [
    {
      "projectName": {
        "branch": [
          {
            "branchName": [
              "path"
            ]
          }
        ],
        "tag": [
          {
            "tagName": [
              "path"
            ]
          }
        ]
      }
    }
  ]
}

While a can to something like that, with the following filter

 .Project=.Project+.Project+
  [{"projectName" : {"branch" : (.branch+[{"branchName":(.tagName+["path"])}]),
             "tag": (.tag+[{"tagName":(.tagName+["path"])}]) }}]

when I want to create another entry in the same project and name, it creates a whole new entry, has if it was a new project, resulting in this:

    {
      "Project": [
        {
          "projectName": {
            "branch": [
              {
                "branchName": [
                  "path"
                ]
              }
            ],
            "tag": [
              {
                "tagName": [
                  "path"
                ]
              }
            ]
          }
        },
        {
          "projectName": {
            "branch": [
              {
                "branchName": [
                  "path"
                ]
              }
            ],
            "tag": [
              {
                "tagName": [
                  "path"
                ]
              }
            ]
          }
        },
        {
          "projectName": {
            "branch": [
              {
                "branchName": [
                  "path2"
                ]
              }
            ],
            "tag": [
              {
                "tagName": [
                  "path2"
                ]
              }
            ]
          }
        }
      ]
    }

But I would like to have

{
  "Project": [
    {
      "projectName": {
        "branch": [
          {
            "branchName": [
              "path",
              "path2"
            ]
          }
        ],
        "tag": [
          {
            "tagName": [
              "path",
              "path2"
            ]
          }
        ]
      }
    }
  ]
}

Is there a way with jq/bash?

3
  • What's the jq string that gives you the wrong result? Commented Aug 20, 2014 at 21:45
  • You're genenerating json from what? A directory structure? A text file? Other json? From nothing? What? Commented Aug 20, 2014 at 22:17
  • @Etan, the jq filter I'm using. Projectname, BranchName, tagName are variable that I should often have the same value, will the path is going to be different at each execution. In fact, this is run by a script that execute a doxygen file on a mercurial repo. So I<m building the docs, then I want to make a page that will allows to select the branch or tag wanted (like release branch) and the version. Commented Aug 20, 2014 at 23:17

1 Answer 1

18

So, I'm taking a stab in the dark here (to mix metaphors), but this gives what seems to be the results you want:

cat test.json | jq '.Project[0].projectName.tag[0].tagName |= .+ ["path2"] | .Project[0].projectName.branch[0].branchName |= .+ ["path2"]'

The |= .+ [...] essentially appends a new array item. You can use the array specs for good effect for all array elements by omitting the 0 from, e.g., tag[0].

This produces:

{
  "Project": [
    {
      "projectName": {
        "tag": [
          {
            "tagName": [
              "path",
              "path2"
            ]
          }
        ],
        "branch": [
          {
            "branchName": [
              "path",
              "path2"
            ]
          }
        ]
      }
    }
  ]
}

Edit -- if I understand the new method now (but I could be missing something), we start with:

{
  "Project": {
    "projectName": {
      "tag": {
        "tagName": [
          "path",
        ]
      },
      "branch": {
        "branchName": [
          "path",
        ]
      }
    }
  }
}

Then set some variables and apply this transform:

Project=projectName ProjectNumber=path2 Branch=branchName Tag=tagName
jq ".Project.${Project}.tag.${Tag} |= .+ [\"${ProjectNumber}\"] | .Project.${Project}.branch.${Branch} |= .+ [\"${ProjectNumber}\"]"

And we get:

{
  "Project": {
    "projectName": {
      "tag": {
        "tagName": [
          "path",
          "path2"
        ]
      },
      "branch": {
        "branchName": [
          "path",
          "path2"
        ]
      }
    }
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

It is not exactly what I wanted, but I can change a bit the format I used to make this work. The tagname, branchname and projectname may vary on each execution, but by removing the array in "tag" and "branch" so that they become objects, it works!
I used this filter: jq ".Project.${Project}.tag.${Tag} |= .+ [\"${ProjectNumber}\"] | .Project.${Project}.branch.${Branch} |= .+ [\"${ProjectNumber}\"]" /var/www/doc/version.json, it does not create the exact result that I wanted, but it's result is close enough that it does what I want. It's just not in arrays.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.