0

I want to use curl to PUT data. This works:

curl -X PUT --data '{ "xy": [0.6476, 0.2727] }' "http://"

I have a couple of bash variables that I'd like to use in place of the literals:

$key="xy"
$value="[0.6476, 0.2727]"

I've tried replacing the literals with quoted vars, but I get an error 'parameter not available'. I've tried combinations of nested and escaped quotes, but I am not getting anywhere.

Lorccan
  • 793
  • 5
  • 20
  • See also [this question](https://stackoverflow.com/q/48470049/3266847) about building a JSON object from Bash variables. – Benjamin W. Dec 04 '19 at 20:05
  • I tried using jq to build the JSON, but I couldn't get it to work with the array (value). -arg worked for the key, but not for the value. I tried -argjson and that rejected it. – Lorccan Dec 04 '19 at 20:08
  • Something [like this](https://stackoverflow.com/a/24300273/3266847) maybe. – Benjamin W. Dec 04 '19 at 20:26
  • See https://stackoverflow.com/questions/59153051/replace-a-key-with-array-in-bash; it uses a new feature in `jq` 1.6 for accessing positional arguments to `jq` as a list. – chepner Dec 04 '19 at 20:35
  • Thank you both. I suspect my problem came from further up the command chain (how the value got assigned to the array variable, which was not as clear cut as I showed) but I got diverted by the failure in `curl` – Lorccan Dec 04 '19 at 20:39

3 Answers3

1

This works for me with Node:

key="xy"
value="[0.6476, 0.2727]"
jsonData=$(node -e "console.log(JSON.stringify({$key: $value}))")
#jsonData output is: {"xy":[0.6476,0.2727]}

curl -X PUT --data $jsonData "http://"

But this only works for Node.js Developer or you have Node environment installed.

Hao
  • 51
  • 3
0

Well this works for me :

 $ key='foo' 
 $ value='[ bar, bar ]' 
 $ echo "{ \"$key\": $value }"
 { "foo": [ bar, bar ] }

So this should work for you as well :

curl -X PUT --data "{ \"$key\": $value }" "http://google.com.uy"

Let me know if it helps!

Matias Barrios
  • 4,674
  • 3
  • 22
  • 49
  • 1
    Thank you. It does work now. I thought I'd tried that combination, but obviously not! – Lorccan Dec 04 '19 at 19:54
  • This is a bad idea. It assumes that neither `key` nor `value` contain any characters that need to be quoted in a valid JSON value. – chepner Dec 04 '19 at 20:34
0

Using jq (1.6 or later), use the --jsonargs option to take multiple JSON-encoded values as a JSON array accessible via $ARGS.positional:

$ key=xy
$ value=(0.6476 0.2727)
$ jq -n '{($k): $ARGS.positional}' --arg k "$key" --jsonargs "${value[@]}"
{
  "xy": [
    0.6476,
    0.2727
  ]
}

--jsonargs must come last, so that all remaining arguments are treated as values in the desired array. We use --jsonargs rather than --args so that you get an array of floating-point values, rather than an array of strings.

Once you have jq working, you pipe its output to curl, which uses - as the argument to --data to read the data from the pipe.

jq -n '{($k): $ARGS.positional}' --arg k "$key" --jsonargs "${value[@]}" |
   curl -X PUT --data - "http://"
chepner
  • 497,756
  • 71
  • 530
  • 681
  • Could you explain this a little please. It looks like just what I'm after, but I'm not really sure what '{($k): $ARGS.positional}' is doing. – Lorccan Dec 05 '19 at 10:36
  • The parentheses are required to force `$k` to be evaluated as an expression, rather than an ill-formed literal key. `$ARGS.positional` is an expression that evaluates to an array containing all the arguments that follow the `--args` option. – chepner Dec 05 '19 at 12:18
  • My `value` is set to a string containing the array I need to send (per my question), so my jsonargs part is `--jsonargs "[nnn, nnn]"` which is outputting `[[nnn nnn]]`. How can I get rid of that extra pair of square brackets please? – Lorccan Dec 05 '19 at 12:45