How to model boolean expressions in JSON tree structure - json

I've spent a few hours on google and stack overflow, but I'm yet to come to a conclusion on just how to model nested boolean data.
Let's say I have the following expression:
123 and 321 and (18 or 19 and (20 or 21))
How could I model this in a JSON tree structure so that I could rebuild the expression as you see it above by simply traversing the tree? I don't need to actually evaluate the logic, but simply structure it in such a way that it portrays the logic in tree-form.
Thanks in advance.
For the record, this is the type of system I'm trying to accomplish and how I'm guessing the tree should be structured based on the answer below.
ANY OF THESE:
13
14
ALL OF THESE:
18
19
20
or
/ \
or 13
/ \
14 and
/ \
and 18
/ \
20 19

My ConditionSet in json format :
"FilterCondition": {
"LogicalOperator": "AND",
"Conditions": [
{
"Field": "age",
"Operator": ">",
"Value": "8"
},
{
"LogicalOperator": "OR",
"Conditions": [
{
"Field": "gender",
"Operator": "=",
"Value": "female"
},
{
"Field": "occupation",
"Operator": "IN",
"Value": ["business","service"]
}
]
}
]
}
Reference : https://zebzhao.github.io/Angular-QueryBuilder/demo/

Think about which order the programming language would evaluate the parts of your statement in. Depending on the precedence of and and or and their left or right associativity, it will have to pick some part that is the 'deepest' and it must be evaluated first, then it is given to its 'parent' (the closest less associative operator) as one of its fully evaluated operands, then when that is evaluated it has a parent and so on.
So, you would have a tree where the root is reached after full evaluation, and leaf nodes are the parts of the expression that can be evaluated first (don't rely on any evaluations to come to their result).
As a simple example,1 and (2 OR 3) would be modelled as
and
/ \
1 or
/ \
2 3
If operators at the same precedence are evaluated left to right and AND is higher precedence than OR (for example true in C++: http://en.cppreference.com/w/cpp/language/operator_precedence ) then
123 and 321 and (18 or 19 and (20 or 21))
becomes
and
/ \
and \
/ \ \
123 321 \
\
or
/ \
18 and
/ \
or 19
/ \
20 21
And to evaluate the result of this tree, you would evaluate deepest first, replacing each node with the result of evaluating its left and its right with its current operator until there is only one number left in the root.
To go from a boolean expression to a boolean expression tree programatically you need to write a parser*, for example in Python you would write it using PLY http://www.dabeaz.com/ply/ and each language has a different third party parser construction library that is the most popular.

Related

Postgres json to view

I have a table like this (with an jsonb column):
https://dbfiddle.uk/lGuHdHEJ
If I load this json with python into a dataframe:
import pandas as pd
import json
data={
"id": [1, 2],
"myyear": [2016, 2017],
"value": [5, 9]
}
data=json.dumps(data)
df=pd.read_json(data)
print (df)
I get this result:
id myyear value
0 1 2016 5
1 2 2017 9
How can a get this result directly from the json column via sql in a postgres view?
Note: This assumes that your id, my_year, and value array are consistent and have the same length.
This answer uses PostgresSQL's json_array_elements_text function to explode array elements to the rows.
select jsonb_array_elements_text(payload -> 'id') as "id",
jsonb_array_elements_text(payload -> 'bv_year') as "myyear",
jsonb_array_elements_text(payload -> 'value') as "value"
from main
And this gives the below output,
id myyear value
1 2016 5
2 2017 9
Although this is not the best design to store the properties in jsonb object and could lead to data inconsistencies later. If it's in your control I would suggest storing the data where each property's mapping is clear. Some suggestions,
You can instead have separate columns for each property.
If you want to store it as jsonb only then consider [{id: "", "year": "", "value": ""}]

Looking for a little assistance working with Powershell and JSON

I have next to zero programming experience but I've done a tiny bit of work with with Powershell so I've picked this for a little project I'm working on. I'm trying to pull some information from JSON and so far have been able to figure it out as I go but the result is formatted strangely which is throwing me for a loop. Here's a snippet of the JSON result:
"data": {
"reviews": [
{
"available_at": "2021-06-18T12:00:00.000000Z",
"subject_ids": [
7572,
3428,
759,
732,
712,
718,
731
]
},
{
"available_at": "2021-06-18T22:00:00.000000Z",
"subject_ids": [
730,
710,
854,
1029,
2938,
736,
734
]
},
{
"available_at": "2021-06-19T03:00:00.000000Z",
"subject_ids": [
3493,
3086,
3091,
2847
]
}
]
}
}
What I want to do is get a count of each set of data.reviews.subject_ids. By using ($summary.data.reviews.subject_ids | Measure-Object).count I get a result of 18, which is to be expected, since there are 18 subject_ids. I only want the count of the first group of 7 though and I can't figure out how to get this from the first set but not the second, third etc. How can I do this?
$summary.data.reviews is an array of 3 children (i.e. the available_at and subject_ids blocks).
At the moment you're counting the number of items in the subject_ids property for all 3 children.
If you want to just select the first one you can use:
$summary.data.reviews[0]
Note that arrays are zero-indexed in PowerShell so the first index is [0], the second is [1] and the Nth is [N-1].
Your code then becomes:
($summary.data.reviews[0].subject_ids | Measure-Object).Count
#7
Today, you're using this syntax $summary.data.reviews.subject_ids, which says give me all of the subject_ids of all reviews inside of summary.data.
The item you want though is the first member of the array of reviews. We can get that by using indexing notation like this,$summary.data.reviews[0], which says "give me the first item in reviews".
PowerShell starts counting from 0, like a lot of programming languages, so that's why we say 0 to mean the first one in the list.
You can then dereference the specific fields you want, just like before, with this syntax $summary.data.reviews[0].subject_ids.
Use the position of the array you want to count.
From about Arrays:
You can refer to the elements in an array by using an index, beginning at position 0. Enclose the index number in brackets.
PS /> $json.data.reviews
available_at subject_ids
------------ -----------
2021-06-18T12:00:00.000000Z {7572, 3428, 759, 732...}
2021-06-18T22:00:00.000000Z {730, 710, 854, 1029...}
2021-06-19T03:00:00.000000Z {3493, 3086, 3091, 2847}
PS /> $json.data.reviews.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS /> $json.data.reviews
available_at subject_ids
------------ -----------
2021-06-18T12:00:00.000000Z {7572, 3428, 759, 732...}
2021-06-18T22:00:00.000000Z {730, 710, 854, 1029...}
2021-06-19T03:00:00.000000Z {3493, 3086, 3091, 2847}
PS /> $json.data.reviews[0]
available_at subject_ids
------------ -----------
2021-06-18T12:00:00.000000Z {7572, 3428, 759, 732...}
PS /> $json.data.reviews[0].subject_ids.Count
7
If you want to iterate over all elements and get their count you can do like this:
$i=1;foreach($object in $json.data.reviews)
{
"- Group $i has {0}" -f $object.subject_ids.count
$i++
}
Which yields:
- Group 1 has 7
- Group 2 has 7
- Group 3 has 4

Azure ARM Template Condition with AND operator

Is it possible to use an AND operator in a condition? For example, if first Parameter is "Apple" and second Parameter B is "Banana" then deploy a resource? My example below is only for if Parameter A is "Yes"
"condition": "[equals(parameters('firstParameter'), 'Apple')]",
"apiVersion": "2017-05-10",
"name": "deployRandomResource",
"type": "Microsoft.Resources/deployments",
yeah, just nest those one inside the other:
"[and(equals(fooooo), equals(baaaaar))]"
you can also nest more expressions:
"[not(or(equals(something, something), and(something, something)))]"
^ ^ if any of the arguments are true - or returns true
^ this read like invert the result: true becomes false and false becomes true

How to evaluate JSON Path with fields that contain quotes inside a value?

I have a NiFi flow that takes JSON files and evaluates a JSON Path argument against them. It work perfectly except when dealing with records that contain Korean text. The Jayway JSONPath evaluator does not seem to recognize the escape "\" in the headline field before the double quote character. Here is an example (newlines added to help with formatting):
{"data": {"body": "[이데일리 김관용 기자] 우리 군이 2018 남북정상회담을 앞두고 남
북간 군사적 긴장\r\n완화와 평화로운 회담 분위기 조성을 위해 23일 0시를 기해 군사분계선
(MDL)\r\n일대에서의 대북확성기 방송을 중단했다.\r\n\r\n국방부는 이날 남북정상회담 계기
대북확성기 방송 중단 관련 내용을 발표하며\r\n“이번 조치가 남북간 상호 비방과 선전활동을
중단하고 ‘평화, 새로운 시작’을\r\n만들어 나가는 성과로 이어지기를 기대한다”고 밝혔
다.\r\n\r\n전방부대 우리 군 장병이 대북확성기 방송을 위한 장비를 점검하고 있다.\r\n[사
진=국방부공동취재단]\r\n\r\n\r\n\r\n▶ 당신의 생활 속 언제 어디서나 이데일리 \r\n▶
스마트 경제종합방송 ‘이데일리 TV’ | 모바일 투자정보 ‘투자플러스’\r\n▶ 실시간 뉴스와
속보 ‘모바일 뉴스 앱’ | 모바일 주식 매매 ‘MP트래블러Ⅱ’\r\n▶ 전문가를 위한 국내 최상의
금융정보단말기 ‘이데일리 마켓포인트 3.0’ | ‘이데일리 본드웹 2.0’\r\n▶ 증권전문가방송
‘이데일리 ON’ 1666-2200 | ‘ON스탁론’ 1599-2203\n<ⓒ종합 경제정보 미디어 이데일리 -
무단전재 & 재배포 금지> \r\n",
"mimeType": "text/plain",
"language": "ko",
"headline": "국방부 \"軍 대북확성기 방송, 23일 0시부터 중단\"",
"id": "EDYM00251_1804232beO/5WAUgdlYbHS853hYOGrIL+Tj7oUjwSYwT"}}
If this object is in my file, the JSON path evaluates blanks for all the path arguments. Is there a way to force the Jayway engine to recognize the "\"? It appears to function correctly in other languages.
I was able to resolve this after understanding the difference between definite and indefinite paths. The Jayway github README points out the following will make a path indefinite and return a list:
When evaluating a path you need to understand the concept of when a
path is definite. A path is indefinite if it contains:
.. - a deep scan operator
?(<expression>) - an expression
[<number>, <number> (, <number>)] - multiple array indexes Indefinite paths
always returns a list (as represented by current JsonProvider).
My JSON looked like the following:
{
"Version":"14",
"Items":[
{"data": {"body": "[이데일리 ... \r\n",
"mimeType": "text/plain",
"language": "ko",
"headline": "국방부 \"軍 ... 중단\"",
"id": "1"}
},
{"data": {"body": "[이데일리 ... \r\n",
"mimeType": "text/plain",
"language": "ko",
"headline": "국방부 \"軍 ... 중단\"",
"id": "2"}
...
}
]
}
This JSON path selector I was using ($.data.headline) did not grab the values as I expected. It instead returned null values.
Changing it to $.Items[*].data.headline or $..data.headline returns a list of each headline.

Dataframe in R to be converted to sequence of JSON objects

I had asked the same question after editing 2 times of a previous question I had posted. I am sorry for the bad usage of this website. I have flagged it for deletion and I am posting a proper new question on the same here. Please look into this.
I am basically working on a recommender system code. The output has to be converted to sequence of JSON objects. I have a matrix that has a look up table for every item ID, with the list of the closest items it is related to and the the similarity scores associated with their combinations.
Let me explain through a example.
Suppose I have a matrix
In the below example, Item 1 is similar to Items 22 and 23 with similarity scores 0.8 and 0.5 respectively. And the remaining rows follow the same structure.
X1 X2 X3 X4 X5
1 22 23 0.8 0.5
34 4 87 0.4 0.4
23 7 92 0.6 0.5
I want a JSON structure for every item (every X1 for every row) along with the recommended items and the similarity scores for each combination as a separate JSON entity and this being done in sequence. I don't want an entire JSON object containing these individual ones.
Assume there is one more entity called "coid" that will be given as input to the code. I assume it is XYZ and it is same for all the rows.
{ "_id" : { "coid" : "XYZ", "iid" : "1"}, "items" : [ { "item" : "22", "score" : 0.8},{ "item": "23", "score" : 0.5}] }
{ "_id" : { "coid" : "XYZ", "iid" : "34"},"items" : [ { "item" : "4", "score" : 0.4},{ "item": "87", "score" : 0.4}] }
{ "_id" : { "coid" : "XYZ", "iid" : "23"},"items" : [ { "item" : "7", "score" : 0.6},{ "item": "92", "score" : 0.5}] }
As in the above, each entity is a valid JSON structure/object but they are not put together into a separate JSON object as a whole.
I appreciate all the help done for the previous question but somehow I feel this new alteration I have here is not related to them because in the end, if you do a toJSON(some entity), then it converts the entire thing to one JSON object. I don't want that.
I want individual ones like these to be written to a file.
I am very sorry for my ignorance and inconvenience. Please help.
Thanks.
library(rjson)
## Your matrix
mat <- matrix(c(1,34,23,
22, 4, 7,
23,87,92,
0.8, 0.4, 0.6,
0.5, 0.4, 0.5), byrow=FALSE, nrow=3)
I use a function (not very interesting name makejson) that takes a row of the matrix and returns a JSON object. It makes two list objects, _id and items, and combines them to a JSON object
makejson <- function(x, coid="ABC") {
`_id` <- list(coid = coid, iid=x[1])
nitem <- (length(x) - 1) / 2 # Number of items
items <- list()
for(i in seq(1, nitem)) {
items[[i]] <- list(item = x[i + 1], score = x[i + 1 + nitem])
}
toJSON(list(`_id`=`_id`, items=items))
}
Then using apply (or a for loop) I use the function for each row of the matrix.
res <- apply(mat, 1, makejson, coid="XYZ")
cat(res, sep = "\n")
## {"_id":{"coid":"XYZ","iid":1},"items":[{"item":22,"score":0.8},{"item":23,"score":0.5}]}
## {"_id":{"coid":"XYZ","iid":34},"items":[{"item":4,"score":0.4},{"item":87,"score":0.4}]}
## {"_id":{"coid":"XYZ","iid":23},"items":[{"item":7,"score":0.6},{"item":92,"score":0.5}]}
The result can be saved to a file with cat by specifying the file argument.
## cat(res, sep="\n", file="out.json")
There is a small difference in your output and mine, the numbers are in quotes ("). If you want to have it like that, mat has to be character.
## mat <- matrix(as.character(c(1,34,23, ...
Hope it helps,
alex