Sunday, February 27, 2022

[SOLVED] JQ merge WooCommerce REST API responce

Issue

Im trying to parse data from woocommerce from linux console. Need to take only shipping info and item names with quantity.

im making curl request to wp-json/wc/v2/orders/ORDER_ID
then jq '{order_id:.id,ship_info:.shipping,items: (.line_items[] | {name , quantity} ) }'
If order contains two items, jq will return two objects
example:

{
  "order_id": 1234,
  "ship_info": {
    "first_name": "Sam",
    "last_name": "Fisher",
    "company": "",
    "address_1": "24 Mega Drive",
    "address_2": "",
    "city": "Eglinton",
    "state": "WA",
    "postcode": "6032",
    "country": "AU",
    "phone": ""
  },
  "items": {
    "name": "Black T-shirt",
    "quantity": 1
  }
}
{
  "order_id": 1234,
  "ship_info": {
    "first_name": "Sam",
    "last_name": "Fisher",
    "company": "",
    "address_1": "24 Mega Drive",
    "address_2": "",
    "city": "Eglinton",
    "state": "WA",
    "postcode": "6032",
    "country": "AU",
    "phone": ""
  },
  "items": {
    "name": "White T-shirt",
    "quantity": 1
  }
}
                                                                                       
                                                                            

I want merge items and use item's name as a key and item's qty as a value. Please advice how to get output like this

{
  "order_id": 1234,
  "ship_info": {
    "first_name": "Sam",
    "last_name": "Fisher",
    "company": "",
    "address_1": "24 Mega Drive",
    "address_2": "",
    "city": "Eglinton",
    "state": "WA",
    "postcode": "6032",
    "country": "AU",
    "phone": ""
  },
  "items": {
    "White T-shirt": "1",
    "Black T-shirt": "1"
  }
}

Solution

With your current jq query you are iterating over the items inside a generated object. That's why you receive one object per item. Rather than merging them afterwards, don't separate them in the first place.

If you changed your query from

jq '{
  order_id: .id,
  ship_info: .shipping,
  items: (.line_items[] | {name, quantity})
}'

to just

jq '{
  order_id: .id,
  ship_info: .shipping,
  items: .line_items
}'

you'd probably already see that .line_items is actually an array.

To transform it according to your desired output, change that line to one of the followings. They should all yield the same result.

  items: (.line_items | map({(.name): .quantity}) | add)
  items: (INDEX(.line_items[]; .name) | map_values(.quantity))
  items: (reduce .line_items[] as $i ({}; .[$i.name] = .quantity))


Answered By - pmf
Answer Checked By - Timothy Miller (WPSolving Admin)