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

7
  • In one place you have "name", in the other you have .names. Make sure your example is internally consistent. Commented Feb 2, 2022 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 and Why is printf better than echo? Commented Feb 2, 2022 at 14:26
  • Getting to your question: Use jq -c to make each item evaluate to one line of output, and a BashFAQ #1 while read loop to iterate over those lines. Commented Feb 2, 2022 at 14:28
  • 1
    The cmd tag is for Microsoft Windows cmd.exe questions. Commented Feb 2, 2022 at 14:28
  • BTW, why two separate copies of jq instead of having the same one that does the select also set class=True? Commented Feb 2, 2022 at 14:30

2 Answers 2

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
Sign up to request clarification or add additional context in comments.

4 Comments

@pmf, can't it be without using loop?
@JohnByro, ...you need some kind of loop no matter what -- how else do you start curl more than once? Using xargs isn't not using a loop; it's just making the loop happen in a C program instead of in your shell interpreter.
Thanks @CharlesDuffy for your valuable discussion
@pmf thanks for your answer
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.

1 Comment

thanks for your answer

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.