3

I'm trying to write a sample script where I'm generating names like 'student-101...student-160'. I need to post JSON data and when I do, I get a JSON parse error.

Here's my script:

name="student-10"

for i in {1..1}
do
    r_name=$name$i
    echo $r_name
    curl -i -H 'Authorization: token <token>' -d '{"name": $r_name, "private": true}' "<URL>" >> create_repos_1.txt
    echo created $r_name
done

I always get a "Problems parsing JSON" error. I've tried various combination of quotes, etc but nothing seems to work!

What am I doing wrong?

Daniel Stenberg
  • 54,736
  • 17
  • 146
  • 222
Saturnian
  • 1,686
  • 6
  • 39
  • 65

3 Answers3

7

First, your name property is a string, so you need to add double quotes to it in your json.

Second, using single quotes, bash won't do variable expansion: it won't replace $r_name with the variable content (see Expansion of variable inside single quotes in a command in bash shell script for more information).

In summary, use:

-d '{"name": "'"$r_name"'", "private": true}'
Derlin
  • 9,572
  • 2
  • 32
  • 53
  • 2
    You now have `$r_name` unquoted, so when the shell expands it, it will be subject to word splitting and pathname expansion. You want `-d '{"name": "'"$r_name"'", "private": true}'` – glenn jackman Sep 08 '17 at 12:43
  • this worked for me. However, I couldn't understand the difference between the quotes :( – Saturnian Sep 08 '17 at 14:09
5

Another option is to use printf to create the data string:

printf -v data '{"name": "%s", "private": true}' "$r_name"
curl -i -H 'Authorization: token <token>' -d "$data" "$url" >> create_repos_1.txt
glenn jackman
  • 238,783
  • 38
  • 220
  • 352
2

Don't; use jq (or something similar) to build correctly quoted JSON using variable inputs.

name="student-10"

for i in {1..1}
do
    r_name=$name$i
    jq -n --arg r_name "$r_name" '{name: $r_name, private: true}' |
      curl -i -H 'Authorization: token <token>' -d @- "<URL>" >> create_repos_1.txt
    echo created $r_name
done

The @- argument tells curl to read data from standard input (via the pipe from jq) to use for -d.


Something like "{\"name\": \"$r_name\", \"private\": true}" may work, but it is ugly and will also fail if r_name contains any character which needs to be quoted in the resulting JSON, such as double quotes or ASCII control characters.

chepner
  • 497,756
  • 71
  • 530
  • 681