Reputation: 66263
I'd like to transform the priceDimension
parts in the following JSON
{
"priceDimensions": {
"222FSQ7X57S9DN65.NQ3QZPMQV9.2TG2D8R56U": {
"unit": "Quantity",
"description": "Upfront Fee",
"USD": "493999"
},
"222FSQ7X57S9DN65.NQ3QZPMQV9.6YS6EN2CT7": {
"unit": "Hrs",
"description": "...",
"USD": "0.0000000000"
}
},
"foo": "bar",
"bla": "blub"
}
into something like this:
{
"priceDimensions": {
"ufrontFee": "493999",
"hourFee": "0.0000000000"
},
"foo": "bar",
"bla": "blub"
}
The following script works if both priceDimension
entries are present:
.priceDimensions |=
{
ufrontFee: .[] | select(.unit == "Quantity").USD,
hourFee: .[] | select(.unit == "Hrs").USD
}
But both entries are in fact optional.
If one is missing then I assumed that only the corresponding key/value has a null
value (e.g. "upFrontFee": null
). But in fact the complete result is null
. Why is that and - of course - how to avoid that efficiently?
Ultimately the key/value for a missing priceDimension
should be omitted alltogetger as shown below. How to do that?
{
"priceDimensions": {
"hourFee": "0.0000000000"
},
"foo": "bar",
"bla": "blub"
}
Edit I have noted that jq-1.5 behaves differently than jq-1.6: After replacing Quantity
with QuantityX
in the example input jq-1.5 outputs:
null
but jq-1.6 (see https://jqplay.org/s/XVgl5UCDLM) outputs
{
"foo": "bar",
"bla": "blub"
}
Upvotes: 2
Views: 86
Reputation: 66263
I have found this solution:
.priceDimensions |=
({ ufrontFee: .[] | select(.unit == "Quantity").USD } // null)
+
({ hourFee: .[] | select(.unit == "Hrs").USD } // null)
Using a custom function I can write it a little bit shorter:
def optional_cost($k; $cmp):
{ ($k): .[] | select(.unit == $cmp).USD } // null;
.priceDimensions |=
optional_cost("ufrontFee"; "Quantity")
+ optional_cost("hourFee"; "Hrs")
Upvotes: 0
Reputation: 116870
Keeping it short and sweet:
.priceDimensions |=
( (first(.[] | select(.description == "Upfront Fee").USD) // null) as $uff
| (first(.[] | select(.unit == "Hrs").USD) // null) as $hf
| if $uff then {ufrontFee: $uff} else null end
+ if $hf then {hourFee: $hf} else null end)
You might want to tweak this to meet your expectations if neither key is present.
This has been tested with jq 1.5 and jq 1.6. For earlier versions of jq, you would have to drop the calls to first
, which are there only for robustness anyway.
Upvotes: 0
Reputation: 2116
Try this,
.priceDimensions |= {
ufrontFee: .[] | select(.unit == "Quantity").USD,
hourFee: .[] | select(.unit == "Hrs").USD
} | delpaths([path(..?) as $p | select(getpath($p) == null) | $p])
Upvotes: 1