I’m looking for a solution to add a new attribute with a JSON object value into an existing JSON file.
My current script:
if [ ! -f "$src_file" ]; then
echo "Source file $src_file does not exists"
exit 1
fi
if [ ! -f "$dst_file" ]; then
echo "Destination file $dst_file does not exists"
exit 1
fi
if ! jq '.devDependencies' "$src_file" >/dev/null 2>&1; then
echo "The key "devDependencies" does not exists into source file $src_file"
exit 1
fi
dev_dependencies=$(jq '.devDependencies' "$src_file" | xargs )
# Extract data from source file
data=$(cat $src_file)
# Add new key-value
data=$(echo $data | jq --arg key "devDependencies" --arg value "$dev_dependencies" '. + {($key): ($value)}')
# Write data into destination file
echo $data > $dst_file
It’s working but the devDependencies
value from $dev_dependencies
is wrote as string:
"devDependencies": "{ @nrwl/esbuild: 15.6.3, @nrwl/eslint-pl[...]"
.
How can I write it as raw JSON ?
2
Answers
I think you want the
--argjson
option instead of--arg
. Comparewith
--arg
will create a string variable. Use--argjson
to parse the value as JSON (can be object, array or number).From the docs:
Note that you don’t need multiple invocations of jq, xargs, command substitution or variables (don’t forget to quote all your variables when expanding).
To "merge" the contents of two files, read both files with jq and let jq do the work. This avoids all the complications that arise from jumping between jq and shell context. A single line is all that’s needed:
or
alternatively (still a one-liner):
peak’s answer here reminded me of the very useful
input
filter, which can make the program even shorter as it avoids the variable: