0

Intention: Need to iterate the each item in json array using jq and proccess seperately

api returns data in form

{
  "name": [
    {
      "first": "first",
      "class": false,
      "type": "B"
    },
    {
      "first": "second",
      "class": false,
      "type": "B"
    },
    {
      "first": "third",
      "class": false,
      "type": "A"
    }
  ]
}

And i am able to parse it as

data=`curl http://some.ur;l`
echo "$data" | jq -rc '.name[] | select(.type=="B") | .class=true'

it returns data as

{"first": "first","class": true, "type": "B"}
{"first": "second", "class": true, "type": "B"}

Now i want to proccess these two outputs in such a way so that i can make a PUT call for each of them . I tried to learn some concepts of xargs but could not make it done

I piped the output to | xargs -n1 but it removed all the quotes from the string

John Byro
  • 674
  • 3
  • 13
  • In one place you have `"name"`, in the other you have `.names`. Make sure your example is internally consistent. – Charles Duffy Feb 02 '22 at 14:25
  • Also, note that `echo $data` is itself buggy and can corrupt your strings. **Always** use quotes, as in, `echo "$data"`, and ideally use `printf` (`printf '%s\n' "$data"`). See [I just assigned a variable, but `echo $variable` shows something else](https://stackoverflow.com/questions/29378566) and [Why is printf better than echo?](https://unix.stackexchange.com/questions/65803/why-is-printf-better-than-echo) – Charles Duffy Feb 02 '22 at 14:26
  • Getting to your question: Use `jq -c` to make each item evaluate to one line of output, and a [BashFAQ #1](https://mywiki.wooledge.org/BashFAQ/001) `while read` loop to iterate over those lines. – Charles Duffy Feb 02 '22 at 14:28
  • 1
    The `cmd` tag is for Microsoft Windows cmd.exe questions. – lit Feb 02 '22 at 14:28
  • BTW, why two separate copies of `jq` instead of having the same one that does the `select` also set `class=True`? – Charles Duffy Feb 02 '22 at 14:30
  • (and yes, as you discovered, you should **never** use `xargs` without `-d $'\n'` or `-0` unless you _want_ it to split on strings, process backslashes and quotes as syntax, etc; this is [BashPitfalls #56](https://mywiki.wooledge.org/BashPitfalls#Using_xargs_without_-0)) – Charles Duffy Feb 02 '22 at 14:31
  • I have edited the question @CharlesDuffy, according to your suggestions. It reduced the pipes. Thanks. It still need something to proccess. – John Byro Feb 02 '22 at 14:33

2 Answers2

0

The only part you're missing is a while read loop.

data=$(curl ...)
while IFS= read -r line; do
  curl -XPUT -d"$line" http://some_url
done < <(jq -c ... <<<"$data")

...or...

curl ... |
  jq -c ... |
  xargs -d $'\n' -n 1 curl -XPUT http://some_url -d

Note:

  • xargs -d $'\n' tells xargs to treat only newlines (and not other whitespace) as separators between items; it also turns off treatment of quotes and backslashes as syntactic rather than literal.
  • xargs -n 1 tells xargs only to pass one data item to each copy of curl.
  • Making the last argument to curl be -d means that xargs will place the data immediately after that position.
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
0

You could loop through using while read:

while IFS= read -r line
do
  
  # your PUT goes here

  # dummy
  printf 'PUTting JSON: %s\n' "$line"

done < <(jq -c '.name[] | select(.type == "B") | .class = true')

If you absolutely need to use xargs then use a newline character as delimiter

jq -c '.name[] | select(.type == "B") | .class = true' \
| xargs -d $'\n' printf 'PUTting JSON: %s\n' # dummy
pmf
  • 24,478
  • 2
  • 22
  • 31