How to run JSONiq from JSON with try.zorba.io - json

I need to write a JSONiq expression that lists only the name of the products that cost at least 3. This is my JSON file which i had typed in the XQuery section:
{ "supermarket_visit":{
"date":"08032019",
"bought":[
"item",{
"type":"confectionary",
"item_name":"Kit_Kat",
"number": 3,
"individual_price": 3.5
},
"item",{
"type":"drinks",
"item_name":"Coca_Cola",
"number": 2,
"individual_price": 3
},
"item",{
"type":"fruits",
"item_name":"apples",
"number": "some"
}
], 
"next_visit":[
"item",{
"type":"stationary",
"item_name":"A4_paper",
"number": 1
},
"item",{
"type":"stationary",
"item_name":"pen",
"number": 2
}
]
}
}
and this is my JSONiq Xquery JSONiq command, which i dont really know where to type in try.zorba.io:
let $x := find("supermarket_visit")
for $x in $supermarket.bought let $i := $x.item
where $i.individual_price <=3
return $i.item_name
I am getting many errors in try.zorba.io and im really new to JSONiq and JSON. Is something wrong with my JSON or JSONiq part?

The following selection works for me at the site you linked to:
jsoniq version "1.0";
{ "supermarket_visit":{
"date":"08032019",
"bought":[
"item",{
"type":"confectionary",
"item_name":"Kit_Kat",
"number": 3,
"individual_price": 3.5
},
"item",{
"type":"drinks",
"item_name":"Coca_Cola",
"number": 2,
"individual_price": 3
},
"item",{
"type":"fruits",
"item_name":"apples",
"number": "some"
}
],
"next_visit":[
"item",{
"type":"stationary",
"item_name":"A4_paper",
"number": 1
},
"item",{
"type":"stationary",
"item_name":"pen",
"number": 2
}
]
}
}.supermarket_visit.bought()[$$ instance of object and $$.individual_price le 3].item_name

The original query can be slightly modified to (in order to keep a FLWOR expression):
jsoniq version "1.0";
let $document := { (: put the document here :) }
for $x in $document.supermarket_visit.bought[]
where $x instance of object and $x.individual_price le 3
return $x.item_name
Note that try.zorba.io is an older version of Zorba (2.9) that does not implement the latest, stable JSONiq version. This is why () must be used instead of [] on this specific page. If you download the latest version of Zorba, the above query should work.
Also, the original document provided in the question is not well-formed JSON, because it contains a special em space character (Unicode 2003) on the line above "next_visit". This character must be removed for this JSON to be parsed successfully.

Related

Change name of main row Rails in JSON

So i have a json:
{
"code": "Q0934X",
"name": "PIDBA",
"longlat": "POINT(23.0 33.0)",
"altitude": 33
}
And i want to change the column code to Identifier
The wished output is this
{
"Identifier": "Q0934X",
"name": "PIDBA",
"longlat": "POINT(23.0 33.0)",
"altitude": 33
}
How can i do in the shortest way? Thanks
It appears that both "the json" you have and your desired result are JSON strings. If the one you have is json_str you can write:
json = JSON.parse(json_str).tap { |h| h["Identifier"] = h.delete("code") }.to_json
puts json
#=> {"name":"PIDBA","longlat":"POINT(23.0 33.0)","altitude":33,"Identifier":"Q0934X"}
Note that Hash#delete returns the value of the key being removed.
Perhaps transform_keys is an option.
The following seems to work for me (ruby 2.6):
json = JSON.parse(json_str).transform_keys { |k| k === 'code' ? 'Identifier' : k }.to_json
But this may work for Ruby 3.0 onwards (if I've understood the docs):
json = JSON.parse(json_str).transform_keys({ 'code': 'Identifier' }).to_json

JMeter: How can I randomize post body data several times?

I have a post body data as:
"My data": [{
"Data": {
"var1": 6.66,
"var2": 8.88
},
"var3": 9
}],
Here, if I post these details on POST DATA body, it will call "My Data" just once. I want to make it random as starting from 1 to 10 times so that "My data" is running for several times but randomly. If the random value is 2, then "My data" should run twice.
Help appreciated!
If you need to generate more blocks like this one:
{
"Data": {
"var1": 6.66,
"var2": 8.88
},
"var3": 9
}
It can be done using JSR223 PreProcessor and the following code:
def myData = []
1.upto(2, {
def entry = [:]
entry.put('Data', [var1: 6.66, var2: 8.88])
entry.put('var3', '9')
myData.add(entry)
})
vars.put('myData', new groovy.json.JsonBuilder(myData).toPrettyString())
log.info(vars.get('myData'))
The above example will generate 2 blocks:
If you want 10 - change 2 in the 1.upto(2, { line to 10
The generated data can be accessed as ${myData} where needed.
More information:
Apache Groovy - Parsing and producing JSON
Apache Groovy - Why and How You Should Use It

JSONiq - how do you convert an array to a sequence?

Using the JSONiq to JavaScript implementation of JSONiq, say I have an array
let $a := [1,2,3]
I'd like to get the elements as a sequence, but all of these return the array itself -
return $a()
return $a[]
return members($a)
What is the correct way to extract the members of the array?
My ultimate goal is to convert objects in an array to strings, like so -
let $updates := [
{"address": "%Q0.1", "keys": ["OUT2", "output.2"], "value": 0},
{"address": "%Q0.7", "keys": ["OUT8", "output.8"], "value": 1}
]
for $update in $updates()
return "<timestamp>|address|" || $update.address
in order to convert an array of JSON objects to a set of strings like <timestamp>|address|%Q0.7, etc
Edit: Using Zorba the $a() syntax seems to work okay - is it an issue with the node jsoniq parser?
e.g.
jsoniq version "1.0";
let $updates := [
{"address": "%Q0.1", "keys": ["OUT2", "output.2"], "value": 0},
{"address": "%Q0.7", "keys": ["OUT8", "output.8"], "value": 1}
]
for $update in $updates()
return current-dateTime() || "|address|" || $update.address
returns
2021-02-19T23:10:13.434273Z|address|%Q0.1 2021-02-19T23:10:13.434273Z|address|%Q0.7
In the core JSONiq syntax, an array is turned into a sequence (i.e., its members are extracted) with an empty pair or square brackets, like so:
$array[]
Example:
[1, 2, 3, 4][]
returns the sequence:
(1, 2, 3, 4)
This means that the query would be:
let $updates := [
{"address": "%Q0.1", "keys": ["OUT2", "output.2"], "value": 0},
{"address": "%Q0.7", "keys": ["OUT8", "output.8"], "value": 1}
]
for $update in $updates[]
return "<timestamp>|address|" || $update.address
The function-call-like notation with an empty pair of parenthesis dates back to JSONiq's early days, as it was primarily designed as an extension to XQuery and maps and arrays were navigated with function calls ($object("foo"), $array(), $array(2)). As JSONiq started having its own life, though, more user-friendly and intuitive syntax for JSON navigation was introduced:
$array[[1]]
for array member lookup given a position
$object.foo
for object lookup given a key and
$array[]
for array unboxing.
While the JSONiq extension to XQuery still exists for scenarios in which users need both JSON and XML support (and is supported by Zorba 3.0, IBM Websphere, etc), the core JSONiq syntax is the main one for all engines that specifically support JSON, like Rumble.
Some engines (including Zorba 3.0) support both the core JSONiq syntax and the JSONiq extension to XQuery, and you can pick the one you want with a language version declaration:
jsoniq version "1.0";
[1, 2, 3, 4][]
vs.
xquery version "3.0";
[1, 2, 3, 4]()
Zorba is relatively lenient and will probably even accept both () and [] in its core JSONiq implementation.
(Warning: Zorba 2.9 doesn't support the latest core JSONiq syntax, in particular the try.zorba.io page still runs on Zorba 2.9. You need to download Zorba 3.0 and run it locally if you want to use it).
A final note: JSON navigation works in parallel, on sequences of arrays and objects, too:
(
{"foo":1},
{"foo":2},
{"foo":3},
{"foo":4}
).foo
returns
(1, 2, 3, 4)
while
(
[1, 2],
[3, 4, 5],
[6, 7, 8]
)[]
returns
(1, 2, 3, 4, 5, 6, 7, 8)
This makes it very easy and compact to navigate large sequences:
$collection.foo[].bar[[1]].foobar[].foo

Python: JSON to Dictionary

Two examples for a JSON request. Both examples should have the correct JSON syntax, yet only the second version seems to be translatable to a dictionary.
#doesn't work
string_js3 = """{"employees": [
{
"FNAME":"FTestA",
"LNAME":"LTestA",
"SSN":6668844441
},
{
"FNAME":"FTestB",
"LNAME":"LTestB",
"SSN":6668844442
}
]}
"""
#works
string_js4 = """[
{
"FNAME":"FTestA",
"LNAME":"LTestA",
"SSN":6668844441
},
{
"FNAME":"FTestB",
"LNAME":"LTestB",
"SSN":6668844442
}]
"""
This gives an error, while the same with string_js4 works
L1 = json.loads(string_js3)
print(L1[0]['FNAME'])
So I have 2 questions:
1) Why doesn't the first version work
2) Is there a simple way to make the first version also work?
Both of these strings are valid JSON. Where you are getting stuck is in how you are accessing the resulting data structures.
L1 (from string_js3) is a (nested) dict;
L2 (from string_js4) is a list of dicts.
Walkthrough:
import json
string_js3 = """{
"employees": [{
"FNAME": "FTestA",
"LNAME": "LTestA",
"SSN": 6668844441
},
{
"FNAME": "FTestB",
"LNAME": "LTestB",
"SSN": 6668844442
}
]
}"""
string_js4 = """[{
"FNAME": "FTestA",
"LNAME": "LTestA",
"SSN": 6668844441
},
{
"FNAME": "FTestB",
"LNAME": "LTestB",
"SSN": 6668844442
}
]"""
L1 = json.loads(string_js3)
L2 = json.loads(string_js4)
The resulting objects:
L1
{'employees': [{'FNAME': 'FTestA', 'LNAME': 'LTestA', 'SSN': 6668844441},
{'FNAME': 'FTestB', 'LNAME': 'LTestB', 'SSN': 6668844442}]}
L2
[{'FNAME': 'FTestA', 'LNAME': 'LTestA', 'SSN': 6668844441},
{'FNAME': 'FTestB', 'LNAME': 'LTestB', 'SSN': 6668844442}]
type(L1), type(L2)
(dict, list)
1) Why doesn't the first version work?
Because calling L1[0] is trying to return the value from the key 0, and that key doesn't exist. From the docs, "It is an error to extract a value using a non-existent key." L1 is a dictionary with just one key:
L1.keys()
dict_keys(['employees'])
2) Is there a simple way to make the first version also work?
There are several ways, but it ultimately depends on what your larger problem looks like. I'm going to assume you want to modify the Python code rather than the JSON files/strings themselves. You could do:
L3 = L1['employees'].copy()
You now have a list of dictionaries that resembles L2:
L3
[{'FNAME': 'FTestA', 'LNAME': 'LTestA', 'SSN': 6668844441},
{'FNAME': 'FTestB', 'LNAME': 'LTestB', 'SSN': 6668844442}]

Uniform conversion of numeric values to JSON

I'm trying to convert a data.table object to JSON. The columns, which have numeric values, should be converted to JSON values in an "uniform" way, i.e. all values should contain the decimal part, even if it's ".0". What I have is:
library(RJSONIO)
test <- data.table(V1 = c(1.0, 2.0, 4.5, 3.0))
cat(toJSON(test))
{
"V1": [ 1, 2, 4.5, 3 ]
}
However, what I'm trying to do is getting the following output:
{
"V1": [ 1.0, 2.0, 4.5, 3.0 ]
}
I've tried with other libraries such as rjson and I'm getting the same result. I can't seem to find any option that would control this. My last option would be to manually process the output the JSON string, adding the required ".0"s at the end, but I'm wondering if there is a better option. Any help would be greatly appreciated.
The jsonlite has an always_decimal option for this:
> test <- data.table(V1 = c(1.0, 2.0, 4.5, 3.0))
> test
V1
1: 1.0
2: 2.0
3: 4.5
4: 3.0
> jsonlite::toJSON(test, dataframe="columns", always_decimal=TRUE)
{"V1":[1.0,2.0,4.5,3.0]}
It doesn't seem to be strictly "always":
> test$V2 = 1:4
> jsonlite::toJSON(test, dataframe="columns", always_decimal=TRUE)
{"V1":[1.0,2.0,4.5,3.0],"V2":[1,2,3,4]}
but it looks like it does do some inspection of the column types:
> test$V3 = c(1,2,3,4.0)
> jsonlite::toJSON(test, dataframe="columns", always_decimal=TRUE)
{"V1":[1.0,2.0,4.5,3.0],"V2":[1,2,3,4],"V3":[1.0,2.0,3.0,4.0]}
and does decimals for "numeric" and not "integer" columns.
The following code does exactly what you want using format and round to specify the number of decimal places:
library(RJSONIO)
library(data.table)
test <- data.table(V1 = c(1.0, 2.0, 4.5, 3.0))
test$V1 <- format(round(test$V1, 2))
cat(toJSON(test))
results :
{
"V1": [ "1.0", "2.0", "4.5", "3.0" ]
}