I’m trying to iterate over a JSON and add a field to each object in the JSON.
I’m doing this in a Gitlab pipeline stage but I don’t think is important.
The JSON is this:
{
"service10": {
"path_to_file" : "service10.txt"
},
"service192": {
"path_to_file" : "service192.txt"
}
}
What I’m doing is using the path_to_file
to check in a Gitlab repo if that file exists and I need to save the http response, the code now looks as follows:
check_files_existence:
stage: update-external-repo
script:
- apt-get update --fix-missing
- apt-get install jq -y
- HTTP_RESPONSE_CODES=()
# Check for file
- |-
for FILE_TO_CHECK in $(jq -r '.[].path_to_file ' $JSON_TO_READ); do
last_status_code=($(curl [omitted]))
HTTP_RESPONSE_CODES+=($last_status_code)
done
# Write array of responses into artifact
- echo "${HTTP_RESPONSE_CODES[@]}" >> ./http_response_code.txt
artifacts:
paths:
- ./http_response_code.txt
expire_in: 10 min
This generates a .txt file with the http responses separated by a whitespace.
What I want to do is add a field to each service while I loop over them with the http_response, so the JSON will be like:
{
"service10": {
"path_to_file" : "service10.txt",
"http_response": 200
},
"service192": {
"path_to_file" : "service192.txt",
"http_response": 404
}
}
And then I’m going to export this an artifact to use it in another stage in my Gitlab Pipeline.
Using the above for loop I can get the file path but then it looks like I cannot update the JSON, if I use something like
for OBJECT in $(jq -r '.[] ' $JSON_TO_READ)
I cannot read the file path because using
jq '.path_to_file $OBJECT'
returns an error.
Is there a way to do this?
Thanks.
2
Answers
This probably calls for two separate copies of jq. Assuming your input file were changed to be valid JSON:
Breaking down the shell pipeline:
First, we have a copy of jq that emits a tab-separated stream with your key and value. An entry here would look like:
Next, we have a shell pipeline (running a BashFAQ #1 loop) that reads these two variables, and runs curl (or in the example above, just adds an incrementing number as the status code) to determine the HTTP status code:
Finally, we have another copy of jq that accepts your input file via
--slurpfile
, and reads the stream of tab-separated service keys and HTTP status codes from stdin, using a reducer to incrementally update the status file as new values come in. (Because--slurpfile
contains a list of JSON documents found in the file, not just a single document, we’re referring to$input_file[0]
to refer to the first — and only — document in the file).If your file isn’t too big and you don’t mind reading the same input file multiple times, then here is another solution that should work:
path_to_file
value from entryhttp_response
to entryjq -s
(--slurp
) to reconstruct the object from its entries