I am trying to select 1 price if it exists, otherwise I want to select a "default" price which always exists. My JQ works if the RMP price doesn’t exist, I just get the 1 value back. But as you can see, if RMP exists I end up with 2 entries … one with each price. I am only looking for 1 result back. It will either have the RMP price if it exists, or it will have the RET price. Not sure what I’m doing wrong here.
JSON
[
{
"PartNumber": "ABC123",
"Prices": {
"Pricing": [
{
"@PriceType": "RET",
"Price": {
"#text": "230.3800"
}
},
{
"@PriceType": "LST",
"Price": {
"#text": "230.3800"
}
},
{
"@PriceType": "RMP",
"Price": {
"#text": "152.0000"
}
}
]
}
}
]
JQ
[.[] | {
sku: .PartNumber,
price: (.Prices?.Pricing? | if type == "array" then .[] else . end | if any(.; ."@PriceType" == "RMP") then select(."@PriceType"? == "RMP").Price."#text" else select(."@PriceType"? == "RET").Price."#text" end),
}]
RESULT
[
{
"sku": "ABC123",
"price": "230.3800"
},
{
"sku": "ABC123",
"price": "152.0000"
}
]
>Solution :
The "problem" of your approach is with if type == "array" then .[] else . end. As .Prices.Pricing is indeed an array, this branches to .[], destructuring the array, so the following code is executed three times, once for each item. The first one will produce the default item (as there is nothing else), the second outputs nothing (neither the target nor the default is present), and the third immediately finds the target item.
My approach would be using INDEX to turn the array into an object, and the alternative operator // to select a default if the previous returns null:
map({
sku: .PartNumber,
price: (.Prices.Pricing | INDEX(."@PriceType") | .RMP // .RET | .Price."#text")
})
[
{
"sku": "ABC123",
"price": "152.0000"
}
]