Parse json using jq utility & append fields together

Viewed 103

One of the many thousand json blocks in an array of json blocks looks as follows -

{
  "id": 4409976,
  "name": "MKLIU",
  "version": "1.0",
  "package_type": "generic",
  "status": "default",
  "_links": {
    "web_path": "/part1/part2/ONEMTH/part4/-/part5/part6",
    "delete_api_path": "https://example.com/api/v1/part40/part90/part65/part73"
  },
  "created_at": "2019-01-02T10:52:34.857Z",
  "project_id": 667845,
  "project_path": "hereitis/downloads/ONEMTH/MKLIU",
  "tags": []
}

I am looking to parse the array of json blocks on Ubuntu command line using jq utility

Expected output

667845#MKLIU#ONEMTH

The code I've written so far is as below

curl <some url> | jq -r '.[] | [.project_id, .name, ._links.web_path] | join("#")'

I can't work out how to pull out just the part ONEMTH from ._links.web_path

Could use project_path field too from the json block to parse out the value.

Please could I request some guidance ?

4 Answers

For just the one object you show, which corresponds to your code after .[]: you can use string interpolation and split / array indexing to extract the web path string:

jq -r '"\(.project_id)#\(.name)#\(._links.web_path | split("/")[3])"'

The key is to use the split/1 method on a delimiter(/) and extract the field required by specifying the index

[ .project_id, .name, (._links.web_path | split("/")[3]) ] | join("#")

jqplay - working demo

You can use the following to get the desired output.

echo $(curl <some-url> | jq -r '.[] | [.project_id, .name] | join("#")' && curl <some-url> | jq -r '.[] |  ._links.web_path' | awk -F/ '{ print $4}') | tr ' ' '#'

PS: There may be a more optimal way to achieve this. Comments are welcome!

One can accomplish this with:

$ jq '{ project_id, name, "path": ._links.web_path | split("/") | .[3] } | join ("#")' < example.txt
"667845#MKLIU#ONEMTH"

The project_id and name fields are "passed through" from the input. You didn't specify the exact rules for pulling out your target substring, "ONEMTH", from the _links.web_path key. The above assumes it's always the fourth element resulting from splitting the string on "/". Please update your question if that's not always the case.

The data is then collected into an object, rather than array, and the values joined by the "#" character.

Interestingly, using an array here doesn't seem to work:

$ jq '[.project_id, .name, ._links.web_path | split("/") | .[3]] | join ("#")' < example.txt
jq: error (at <stdin>:14): split input and separator must be strings

I'm not sure why. The jq documentation explicitly states that array elements may be pipelines, so it seems like that should be fine. But in any case, the former works!

Related