I have an associative array that I want to pass to cURL as POST data. However i have tried multiple things, still it doesn't work.
The array:
declare -A details
details[name]="Honey"
details[class]="10"
details[section]="A"
details[subject]="maths"
The cURL commands have tried so far (all of these failed):
resp = $(cURL --request POST --data details "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data variables=details "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data "variables=$details" "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data "variables=${details}" "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data $details "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data ${details} "https://somedomain.net/getMarks")
resp = $(cURL --request POST --data variables=details "https://somedomain.net/getMarks")
Something like shown below, I want the above request to be (indirectly), however I want to pass the array directly instead of writing its contents.
resp = $(cURL --request POST --data '{"variables":[{"name": "Honey"},{"class": "10"},{"section": "A"},{"subject": "maths"}]}' "https://somedomain.net/getMarks")
Please note that to begin with I will always have the associative array ONLY (not any json array or string).
This question rose when I was trying calling cURL command with the associative array as on this link (GITLAB API)(the example does not contain variables array example). Here they have mentioned a variables array (array of hashes).
CodePudding user response:
Assumptions/understandings:
- no need to list the array entries in any particular order
- neither the array indices or values contain newlines
One bash
idea:
# use a function to build the --data component
build_data() {
local -n _arr="$1" # use nameref so we can pass in the name of any associative array
local _sep=""
local _string='{"variables":['
local _i
for i in "${!_arr[@]}"
do
_string="${_string}${_sep}{\"${i}\": \"${_arr[$i]}\"}"
_sep=","
done
printf "%s]}" "${_string}"
}
Adding this to the curl
call:
resp=$(cURL --request POST --data "$(build_data details)" "https://somedomain.net/getMarks")
NOTES:
- no spaces allowed on either side of the
=
, ie,resp = $(curl ...)
needs to beresp=$(curl ...)
- without an actual/valid URL I'm guessing a bit on if/where the escaped quotes belong so may need to tweak the escaped quotes to get working correcly
CodePudding user response:
- Since I had to use an older version of bash, which does not involve the name referencing as stated on the answer, I had to try to code string creation of the associative array without passing it to a function
- Since I always had an associative array to begin with, the process of passing the array as accepted by the gitlab API normally was:
resp=$(cURL --request POST --data '{"variables":[{"name": "Honey"},{"class": "10"},{"section": "A"},{"subject": "maths"}]}' "https://somedomain.net/getMarks")
OR
resp=$(cURL --request POST --data "variables[name]=Honey" --data "variables[class]=10" --data "variables[section]=A" --data "variables[subject]=maths" "https://somedomain.net/getMarks")
So tried some tweaks on the second way and what worked for me was:
_sep=""
_string=""
for index in "${!details[@]}"
do
_string="${_string}${_sep}variables[${index}]="${details[$index]}"
_sep="&"
done
resp=$(cURL --request POST --data "$_string" "https://somedomain.net/getMarks")
#which indirectly was:
resp=$(cURL --request POST --data "variables[name]=Honey&variables[class]=10&variables[section]=A&variables[subject]=maths" "https://somedomain.net/getMarks")
And it was a success. Thanks to @markp-fuso for giving me an intuition of creating a string with his logic above.