出于商业原因,我们需要将一些条件逻辑外部化为外部文件:最好是JSON.
可以通过添加节点来处理简单的过滤方案,如下所示:
"filter": [
{
"criteria": "status",
"value": "open",
"condition": "=="
}
]
Run Code Online (Sandbox Code Playgroud)
多个条件可以通过数组中的其他值来处理.
"filter": [
{
"criteria": "status",
"value": "open",
"condition": "=="
},
{
"criteria": "condition2",
"value": "value2",
"condition": "=="
}
]
Run Code Online (Sandbox Code Playgroud)
但是,当我们处理涉及AND或OR的复杂条件时,它会有点混乱.
问题:在JSON中表示这种逻辑是否有标准化(甚至广泛接受)的格式?如果由你决定,你会怎么做?
注意:第一个答案是一个可编辑的维基,所以任何人都可以改进它.
cHa*_*Hao 55
如果你必须使用标准JSON实现它,我建议类似于Lisp的"S表达式".条件可以是普通对象,也可以是第一个条目是连接它们的逻辑操作的数组.
例如:
["AND",
{"var1" : "value1"},
["OR",
{ "var2" : "value2" },
{ "var3" : "value3" }
]
]
Run Code Online (Sandbox Code Playgroud)
代表var1 == value1 AND (var2 == value2 OR var3 == value3).
如果您更喜欢简洁而不是一致性,那么您还可以允许对象具有多个属性,这些属性将隐式地由AND连接.例如,{ "a": "b", "c": "d" }相当于["AND", { "a": "b" }, { "c": "d" }].但是有些情况(比如示例),前一种语法不能忠实地表示写入的条件; 你需要额外的技巧,比如翻译条件或使用虚拟属性名称.后一种语法应始终有效.
Jer*_*ams 33
我需要一种格式:
所以我构建了一个我称之为JsonLogic的格式.规则是JSON对象,操作符位于键位置,值位置中有一个或一组参数.(受Amazon CloudFormation函数的启发.)任何参数都可以是另一个规则,因此您可以构建任意深度的逻辑.
我还为它编写了两个解析器:JsonLogic for JavaScript和JsonLogic for PHP.
cHao的例子将写成
{ "and", [
{"==", [ {"var" : "var1"}, "value1" ]},
{ "or", [
{"==", [ {"var" : "var2"}, "value2" ]},
{"==", [ {"var" : "var3"}, "value3" ]}
]}
]}
Run Code Online (Sandbox Code Playgroud)
var 这里是获取"data"对象的属性的运算符,与"rule"对象一起传递给解析器,例如:
jsonLogic(
{"==", [{"var":"filling"}, "apple"]} // rule, is this pie apple?
{"filling":"apple", "temperature":100} // data, a pie I'm inspecting
);
// true
Run Code Online (Sandbox Code Playgroud)
有更多可能的运算符(大于,非等于,数组内,三元等),并且两个解析器都可以在GitHub上使用(带有单元测试和文档).
我有类似的需求(在 javascript 中建立一个 sql where 子句)。我创建了以下 javascript 函数:
function parseQuery(queryOperation){
var query="";
if (queryOperation.operator == 'and')
query = "(" + parseQuery(queryOperation.leftOp) + ") AND (" + parseQuery(queryOperation.rightOp) + ")";
if (queryOperation.operator == 'or')
query = "(" + parseQuery(queryOperation.leftOp) + ") OR (" + parseQuery(queryOperation.rightOp) + ")";
if (queryOperation.operator == '=')
query = "(" + queryOperation.leftOp +" = "+ queryOperation.rightOp + ")";
return query;
}
Run Code Online (Sandbox Code Playgroud)
我创建我的 queryOperation 像这样:
var queryObject = {
operator: 'and',
leftOp: {
leftOp: 'tradedate',
operator: '=',
rightOp: new Date()
},
rightOp: {
operator: 'or',
leftOp: {
leftOp: 'systemid',
operator: '=',
rightOp: 9
},
rightOp: {
leftOp: 'systemid',
operator: '=',
rightOp:10
}
}
};
Run Code Online (Sandbox Code Playgroud)
当我将 queryOperation 传递给 ParseQuery 时,它返回 ((tradedate= Thu Jul 24 17:30:37 EDT 2014)) AND (((systemid= 9)) OR ((systemid= 10)))
我需要添加一些类型转换和其他运算符,但基本结构有效。
我提出这种格式的主要目标是尽可能接近实际的 SQL。
这是打字稿中的类型定义:
type LogicalOperator = 'AND' | 'OR';
type Operator = '=' | '<=' | '>=' | '>' | '<' | 'LIKE' | 'IN' | 'NOT IN';
type ConditionParams = {field: string, opp: Operator, val: string | number | boolean};
type Conditions = ConditionParams | LogicalOperator | ConditionsList;
interface ConditionsList extends Array<Conditions> { }
Run Code Online (Sandbox Code Playgroud)
或者 BNF(是吗?我的计算机老师不会感到自豪)
WHEREGROUP: = [ CONDITION | ('AND'|'OR') | WHEREGROUP ]
CONDITION: = {field, opp, val}
Run Code Online (Sandbox Code Playgroud)
具有以下解析规则:
AND是可选的(我通常添加它是为了便于阅读)。如果LogicalOperator条件之间省略了逻辑,它会自动将它们连接起来AND())以下是一些示例(打字稿游乐场链接):
1 和 2(并推断)
[
{ field: 'name', opp: '=', val: '123' },
{ field: 'otherfield', opp: '>=', val: 123 }
]
Run Code Online (Sandbox Code Playgroud)
1 或 2
[
{ field: 'name', opp: '=', val: '123' },
'OR',
{ field: 'annualRevenue', opp: '>=', val: 123 }
]
Run Code Online (Sandbox Code Playgroud)
(1 或 2) 和 (3 或 4)
[
[
{ field: 'name', opp: '=', val: '123' },
'OR',
{ field: 'name', opp: '=', val: '456' }
],
'AND',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
]
Run Code Online (Sandbox Code Playgroud)
1 和(2 或 3)
[
{ field: 'name', opp: '=', val: '123' },
'AND',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
]
Run Code Online (Sandbox Code Playgroud)
1 和 2 或 3
[
{ field: 'name', opp: '=', val: '123' },
'AND',
{ field: 'annualRevenue', opp: '>=', val: 123 },
'OR',
{ field: 'active', opp: '=', val: true }
]
Run Code Online (Sandbox Code Playgroud)
1 或 (2 和 (3 或 4))
[
{ field: 'name', opp: '=', val: '123' },
'OR',
[
{ field: 'annualRevenue', opp: '>=', val: 123 },
'AND',
[
{ field: 'active', opp: '=', val: true },
'OR',
{ field: 'accountSource', opp: '=', val: 'web' }
]
]
]
Run Code Online (Sandbox Code Playgroud)
正如你所看到的,如果你要删除,和 属性名称,然后只需将 替换为[],()你基本上就会得到 SQL 格式的条件
顺便说一下,IBM DB2支持以JSON编码的逻辑语句。
布尔运算看起来像cHao的解决方案与Amazon CloudFormation之间的交叉:
{"$and":[{"age":5},{"name":"Joe"}]}
Run Code Online (Sandbox Code Playgroud)
在我看来,比较操作就像音译SQL一样。(而不是Amazon或Russellg或cHao向抽象语法树的迁移。)
{"age":{"$lt":3}}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30138 次 |
| 最近记录: |