outon
outon

Reputation: 116

JQ show empty or null values and iterate over different keys

I was looking on how to transform a json file using jq that I receive from a webservice to remove depth levels and keep only some values.

https://jqplay.org/s/_RZNr_oYwE

Json file is similar to this:

[
  {
   "date":"2020-04-13",
   "product1":{"p_max":18.00,"p_min":8.00,"interval":[{"time":"06:00:00","price":8.00},{"time":"12:00:00","price":18.00},{"time":"18:00:00","price":16.00},{"time":"24:00:00","price":9.00}]},
   "product2":{"p_max":18.00,"p_min":8.00,"interval":[{"time":"06:00:00","price":8.00},{"time":"12:00:00","price":18.00},{"time":"18:00:00","price":16.00},{"time":"24:00:00","price":9.00}]}
  },
  {
   "date":"2020-04-14",
   "product1":{"p_max":18.00,"p_min":8.00,"interval":[{"time":"06:00:00","price":8.00},{"time":"12:00:00","price":18.00},{"time":"18:00:00","price":16.00},{"time":"24:00:00","price":9.00}]},
   "product2":{"p_max":18.00,"p_min":8.00,"interval":[{"time":"06:00:00","price":9.00},{"time":"12:00:00","price":16.00},{"time":"18:00:00","price":15.00},{"time":"24:00:00","price":11.00}]}
  },
  {
   "date":"2020-04-15",
   "product1":{"p_max":16.00,"p_min":9.00,"interval":[]},
   "product2":{"p_max":16.00,"p_min":9.00,"interval":[]}
  }
]

I figured out how to convert the json but I miss some values:

jq --compact-output '.[] | .product1.interval[] as $interval| {date: .date, time: ($interval.time//"N/A"), price: ($interval.price//-1)}'

This is the output:

{"date":"2020-04-13", "time":"06:00:00", "price":8}
{"date":"2020-04-13", "time":"12:00:00", "price":18}
{"date":"2020-04-13", "time":"18:00:00", "price":16}
{"date":"2020-04-13", "time":"24:00:00", "price":9}
{"date":"2020-04-14", "time":"06:00:00", "price":9}
{"date":"2020-04-14", "time":"12:00:00", "price":16}
{"date":"2020-04-14", "time":"18:00:00", "price":15}
{"date":"2020-04-14", "time":"24:00:00", "price":11}

But I miss:

{"date":"2020-04-15", "time":"N/A", "price":-1}

I also have tried but couldn't, so I guess that I will have to iterate in a bash script to get the following output:

{"date":"2020-04-13", "time":"06:00:00", "product": "product1", "price":8}
{"date":"2020-04-13", "time":"06:00:00", "product": "product2", "price":4}
{"date":"2020-04-13", "time":"12:00:00", "product": "product1", "price":18}
{"date":"2020-04-13", "time":"12:00:00", "product": "product2", "price":8]
{"date":"2020-04-13", "time":"18:00:00", "product": "product1", "price":16}
{"date":"2020-04-13", "time":"18:00:00", "product": "product2", "price":8}
{"date":"2020-04-13", "time":"24:00:00", "product": "product1", "price":9}
{"date":"2020-04-13", "time":"24:00:00", "product": "product2", "price":5}
{"date":"2020-04-14", "time":"06:00:00", "product": "product1", "price":9}
{"date":"2020-04-14", "time":"06:00:00", "product": "product2", "price":6}
{"date":"2020-04-14", "time":"12:00:00", "product": "product1", "price":16}
{"date":"2020-04-14", "time":"12:00:00", "product": "product2", "price":6}
{"date":"2020-04-14", "time":"18:00:00", "product": "product1", "price":15}
{"date":"2020-04-14", "time":"18:00:00", "product": "product2", "price":15}
{"date":"2020-04-14", "time":"24:00:00", "product": "product1", "price":11}
{"date":"2020-04-14", "time":"24:00:00", "product": "product2", "price":11}
{"date":"2020-04-15", "time":"N/A",      "product": "product1", "price":-1}
{"date":"2020-04-15", "time":"N/A",      "product": "product2", "price":-1}

Is there any way to get "empty" values? Is there any way to produce second output with jq with out needing to iterate on bash?

Upvotes: 0

Views: 242

Answers (1)

oguz ismail
oguz ismail

Reputation: 50815

No, you don't need to iterate on bash, JQ can do that on its own.

Get product names using keys_unsorted (which necessitates deleting date) and use an if-then-else expression for alternating an empty interval with [{"time": "N/A", "price": -1}].

.[]
| {date} + (
  del(.date)
  | keys_unsorted[] as $product
  | {$product} + (
    .[$product].interval
    | if . == [] then
        {time: "N/A", price: -1}
      else
        .[]
      end
  )
)

Online demo

Upvotes: 2

Related Questions