How to use JSONiq for JSON - json

The question is to write a JSONiq FLWOR expression that can display the name of the products which their price are at least 3.
I have tried the answers provided on How to run JSONiq from JSON with try.zorba.io but that's not the answers that i expect. Beside that, I also tried a lot of JSON FLWOR expression but still getting errors in try.zobia.io. This is my JSON file.
{
"supermarket": {
"visit": [ {
"_type": "bought",
"date": "March 8th, 2019",
"product": [ {
"name": "Kit Kat",
"amount": 3,
"cost": 3.5
},
{
"name": "Coca Cola",
"amount": 2,
"cost": 3
},
{
"name": "Apple",
"amount": "Some",
"cost": 5.9
}
]
},
{
"_type": "planning",
"product": [{
"name": "Pen",
"amount": 2
},
{
"name": "Paper",
"amount": "One ream"
}
]
}
]
}
}
This is my current JSONiq expression.
jsoniq version "1.0";
let $a := { (: my JSON file :) }
for $x in $a.supermarket.visit
let $y = $x.product()
where $y.price >= "3.0"
return $y.name
The final output should be Kit Kat, Coca Cola and Apple. I would appreciate some helps for my JSON file or JSONiq.

visit also is an array, so you need the parenthesis to get to the individual visits in the for. This
jsoniq version "1.0";
let $data := { (: my JSON file :) }
for $visit in $data.supermarket.visit()
for $product in $visit.product()
where $product.cost ge 3
return $product.name
would return
Kit Kat Coca Cola Apple
Since the above produces a sequence, you can use it anywhere where sequences are allowed.
let $data := { (: my JSON file :) }
return string-join(
for $visit in $data.supermarket.visit()
for $product in $visit.product()
where $product.cost ge 3
return $product.name
, ", ")
Result:
Kit Kat, Coca Cola, Apple
Of course this would work as well:
for $product in $data.supermarket.visit().product()
where $product.cost ge 3
return $product.name

Related

How to get the All index values in Groovy JSON xpath

Please find the attached Groovy code which I am using to get the particular filed from the response body.
Query 1 :
It is retrieving the results when the I am using the correct Index value like if the data.RenewalDetails[o], will give output as Value 1 and if the data.RenewalDetails[1], output as Value 2.
But in my real case, I will never know about number of blocks in the response, so I want to get all the values that are satisficing the condition, I tried data.RenewalDetails[*] but it is not working. Can you please help ?
Query 2:
Apart from the above condition, I want to add one more filter, where "FamilyCode": "PREMIUM" in the Itemdetails, Can you help on the same ?
def BoundId = new groovy.json.JsonSlurper().parseText('{"data":{"RenewalDetails":[{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value1","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]},{"ExpiryDetails":{"duration":"xxxxx","destination":"LHR","from":"AUH","value":2,"segments":[{"valudeid":"xxx-xx6262-xxxyyy-1111-11-11-1111"}]},"Itemdetails":[{"BoundId":"Value2","isexpired":true,"FamilyCode":"PREMIUM","availabilityDetails":[{"travelID":"AAA-AB1234-AAABBB-2022-11-10-1111","quota":"X","scale":"XXX","class":"X"}]}]}]},"warnings":[{"code":"xxxx","detail":"xxxxxxxx","title":"xxxxxxxx"}]}')
.data.RenewalDetails[0].Itemdetails.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33
}?.BoundId
println "Hello " + BoundId
Something like this:
def txt = '''\
{
"data": {
"RenewalDetails": [
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value1",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
},
{
"ExpiryDetails": {
"duration": "xxxxx",
"destination": "LHR",
"from": "AUH",
"value": 2,
"segments": [
{
"valudeid": "xxx-xx6262-xxxyyy-1111-11-11-1111"
}
]
},
"Itemdetails": [
{
"BoundId": "Value2",
"isexpired": true,
"FamilyCode": "PREMIUM",
"availabilityDetails": [
{
"travelID": "AAA-AB1234-AAABBB-2022-11-10-1111",
"quota": "X",
"scale": "XXX",
"class": "X"
}
]
}
]
}
]
},
"warnings": [
{
"code": "xxxx",
"detail": "xxxxxxxx",
"title": "xxxxxxxx"
}
]
}'''
def json = new groovy.json.JsonSlurper().parseText txt
List<String> BoundIds = json.data.RenewalDetails.Itemdetails*.find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.size() == 33 && itemDetail.FamilyCode == 'PREMIUM'
}?.BoundId
assert BoundIds.toString() == '[Value1, Value2]'
Note, that you will get the BoundIds as a List
If you amend your code like this:
def json = new groovy.json.JsonSlurper().parse(prev.getResponseData()
you would be able to access the number of returned items as:
def size = json.data.RenewalDetails.size()
as RenewalDetails represents a List
Just add as many queries you want using Groovy's && operator:
find { itemDetail ->
itemDetail.availabilityDetails[0].travelID.length() == 33 &&
itemDetail.FamilyCode.equals('PREMIUM')
}
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy: What Is Groovy Used For?

JSONata transpose a dynamic sized object

I have a json response from a REST API that looks like:
{
"Data": [
{
"Name": "MeasurementID1",
"Samples": [
{
"Time": "2021-12-31T11:15:00.000Z",
"Value": "3.280642033",
},
{
"Time": "2021-12-31T12:15:00.000Z",
"Value": "0.06151203811",
}
]
},
{
"Name": "MeasurementID2",
"Samples": [
{
"Time": "2021-12-31T11:15:00.000Z",
"Value": "53.91226196",
},
{
"Time": "2021-12-31T12:15:00.000Z",
"Value": "56.34856796",
}
]
}
]
}
I would like to transform this data for plotting in Grafana where the data is an array of table rows like
[
{ "Time": "2021-12-31T11:15:00.000Z", "MeasurementID1": "3.280642033", "MeasurementID2": "53.91226196".........."MeasurementIDxx": xxx},
{ "Time": "2021-12-31T12:15:00.000Z", "MeasurementID1": "0.06151203811", "MeasurementID2": "56.34856796".........."MeasurementIDxx": xxx}
]
I've hit a stumbling block in that the number of objects in the "Data" array is dynamic and is based on the # requested in rest api get request.
I'm stuck and don't have enough knowledge to do this transformation
If you flattened the structure a bit first, you can use the 'group-by' construct:
Data.Samples.{
"Name": %.Name,
"Time": Time,
"Value": Value
}{Time: $} ~> $each(function($v) {
$merge($v.{"Time": Time, Name: Value})
})
See https://try.jsonata.org/NXMIg7e0R
I was able to solve it by using 2 nested $reduce calls. Check it out here: https://stedi.link/egfbW8g
$reduce(Data, function($dataAcc, $dataItem) {(
$reduce($dataItem.Samples, function($samplesAcc, $sampleItem) {(
$existingItemForTime := $lookup($samplesAcc, $sampleItem.Time);
$patchForTime := {"Time": $sampleItem.Time, $dataItem.Name: $sampleItem.Value };
$merge([$samplesAcc, { $sampleItem.Time: $merge([$existingItemForTime, $patchForTime]) }])
)}, $dataAcc);
)}, {}) ~> $each(function($v) { $v })

Extracting a single value from JSON with JSONPATH selector and mulltiple filters

This seems very much possible, but I can't get it to work. Could be my JSON or my jsonpath selector. Not sure.
Here's the simple JSON showing a book inventory with the cost of 10 and 20 copies, along with which ones are On Sale:
{
"Books": {
"1": {
"Title": "Title of the 1st book",
"Cost": {
"10": 19.95,
"20": 29.95
},
"OnSale": 0
},
"2": {
"Title": "Title of the 2nd book",
"Cost": {
"10": 9.95,
"20": 39.95
},
"OnSale": 1
},
"3": {
"Title": "Title of the 3rd book",
"Cost": {
"10": 5.95,
"20": 49.95
},
"OnSale": 0
}
},
"ChosenQuantity": "10"
}
Using the stefan.goessner jsonpath library, I want the cost of 10 books that are On Sale with the following jsonpath selector:
$.Books[?(#.OnSale==1)].Cost[?($.ChosenQuantity)]
I can't hard code any of the key values into the jsonpath selector.
With the above jsonpath, what I'm expecting:
[
9.95
]
Instead, I'm getting the following:
[
9.95,
39.95
]
To test, I've been using https://jsonpath.herokuapp.com/ with the Goessner implementation.
Is the problem in the JSON, the jsonpath selector filters, or both?
Try using:
$.Books[?(#.OnSale==1)].Cost.10
or (depending on where you test it):
$.Books..[?(#.OnSale==1)].Cost.10
It should get you the right value.

Accessing Json Array of objects in React-Native

I'm able to call parcels using map as list.parcels and the output comes like
{parcelId: "12"}
{parcelId: "14"}
{parcelId: "15"}
{parcelId: "16"}
{parcelId: "17"}
but i need to print only parcelId value, so to do that I tried list.parcels.parcelId and it shows undefined. I need help in printing the parcelId alone. Thanks in advance.
Json is as below:
{
"id": "7",
"type": "history",
"title": "History Parcel Delivery",
"sender": "Paul",
"price": "635.50",
"parcels": [
{
"parcelId": "12"
},
{
"parcelId": "14"
},
{
"parcelId": "15"
},
{
"parcelId": "16"
},
{
"parcelId": "17"
}
]
}
Since, list.parcels is an array you must use an index to reference an object within it. So to refer to the first item in the array you should use list.parcels[0].parcelId. This will print "12". So to print a specific parcelId use:
list.parcels[i].parcelId
where value of i is between 0 and one less than the length of the array
If you just need a list of the parcelId you can use
parcelIds = lists.parcels.map((parcel) => parcel.parcelId);
i know it to much late,but i hope its helpfull for others,How to Accessing Json Array of objects in React-Native
{
"name":"John",
"age":30,
"cars":[ "Ford", "BMW", "Fiat" ]
}
var cardatafetch=[]
for (i in myObj.cars) {
var dataa= myObj.cars[i];
//and for push the array data into array var,i declare it above the for loop you can declare any where
cardatafetch.push(dataa)
}
console.log(cardatafetch)

Trouble Parsing Array vs Non-Array JSON with JSONPath

I have JSON that looks like the below. I'm trying to use JSONPath to grab the __ content __ value where the SKU is "8A-OK9F-9LI8" AND the Component.Type == 'Principal'. Right now, I am playing around with this JSON Path Expression Tester.
This JSONPath expression grabs all of the component information I need:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component
But filtering further such as $.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')] grabs only one (I believe the Array one) of the two Component elements I need. I suspect this is because one is an Array and one is a single JSON element. Is it possible to grab this with one command or do I have to combine several commands (one for the Array and one for the single JSON element)? If so, how can I grab the other Component information that I am not currently getting with:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')]?
Again, my goal is to grab the "__ content__" value and filter by a specific SKU and where the Component.Type == 'Principal'. Something like:
$.Order..Fulfillment[?(#.SKU=='8A-OK9F-9LI8')]..Component[?(#.Type=='Principal')]..Amount..__content__
I'm expecting to get back ["8.49", "8.49"]
Here is the JSON I am testing with:
{
"SettlementData": {},
"Order": [
{
"OrderID": "XXX",
"Fulfillment": {
"Item": {
"SKU": "8A-OK9F-9LI8",
"Quantity": "1",
"ItemPrice": {
"Component": [
{
"Type": "Principal",
"Amount": {
"__content__": "8.49",
"currency": "USD"
}
},
{
"Type": "Tax",
"Amount": {
"__content__": "0.74",
"currency": "USD"
}
}
]
}
}
}
},
{
"OrderID": "XXX",
"Fulfillment": {
"Item": {
"SKU": "8A-OK9F-9LI8",
"Quantity": "1",
"ItemPrice": {
"Component": {
"Type": "Principal",
"Amount": {
"__content__": "8.49",
"currency": "USD"
}
}
}
}
}
}
]
}
I was able to solve this in two passes. In this example, #{sku} is a Ruby interpolated string that contains the SKU I am passing in:
$.Order..Fulfillment[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__
$.Order..Fulfillment..Item[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__
Using a Ruby gem "jsonpath", I was able to get the amounts I needed like this:
amount = JsonPath.on(settlement, "$.Order..Fulfillment[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__")
.map(&:to_f).inject(:+)
amount2 = JsonPath.on(settlement, "$.Order..Fulfillment..Item[?(#.SKU=='#{sku}')]..ItemPrice..[?(#.Type=='Principal')].Amount.__content__")
.map(&:to_f).inject(:+)