使用结构化json确定truthy逻辑,如何使用javascript最终返回布尔值?
考虑以下使用结构化json确定truthy逻辑,如何使用javascript最终返回布尔值?,javascript,json,Javascript,Json,考虑以下JSON逻辑示例,当您看到值属性时,它从用户输入中导出其值,并将其与表达式进行比较: { "truthy": [ [ "AND", { "operator": "=", "compareType": "text", "value": "fname"
JSON
逻辑示例,当您看到值
属性时,它从用户输入中导出其值,并将其与表达式进行比较:
{
"truthy": [
[
"AND",
{
"operator": "=",
"compareType": "text",
"value": "fname",
"expression": "John"
},
{
"operator": "=",
"compareType": "text",
"value": "lname",
"expression": "Doe"
}
],
"OR",
{
"operator": "=",
"compareType": "boolean",
"value": "Agree",
"expression": true
},
"OR",
[
"AND",
{
"operator": "=",
"compareType": "text",
"value": "fname",
"expression": "Jane"
},
{
"operator": "=",
"compareType": "text",
"value": "lname",
"expression": "Doe"
}
]
]
}
翻译后的表达是:
(fname === "John" && lname === "Doe") || agree === true || (fname === "Jane" && lname === "Doe")
eval("(true === true) || true === false || (true === false)")
现在我要做的是迭代结构并将值推送到数组,然后使用eval
返回true
或false
for (i; i < v.length; i++) {
if (Array.isArray(v[i])) {
e.push("(true===");
e.push(this.parseBlocks(v[i], a, 0));
e.push(")");
} else if (v[i] === "OR") {
e.push("||");
} else if (v[i] === "AND") {
e.push("&&");
} else {
e.push(true);
e.push("===");
e.push(this.parseBlocks([v[i]], a, 0));
}
}
return eval(e.join(""));
当它是一个更简单的表达式时,我不需要构造这个字符串来求值。例如,所有内容之间的两个或多个字符串
未包含的代码是实际的解析函数,但它所做的是获取数组中的第一个元素(即“AND”、“OR”),并使用该元素确定该特定逻辑块是否返回true或false
如果考虑到潜在的更深层次的逻辑嵌套,在不使用eval的情况下确定结果,或者考虑到我正在控制传递到eval的内容,那么如何处理这个问题呢?相比之下,它可能提供更好的性能
要求:
在国际海事组织,您需要两个功能:
- 一个是用对象、数组等解析json的一般结构。。。这是我的
评估
- 一个用于评估最终对象。这是我的
leafValue
1-
leafValue
这是最直接的。您只需要从一组数据进行评估。在这里,我创建了一个名为data
的对象,但在您的问题中,您似乎希望从当前范围(fname
而不是someObject.fname
)中获取值,因此您也可以用这个替换我的数据
然后,我实现了一个简单的开关/case
来解释不同的操作符的值。如果您还想实现更复杂的compareType
选项,则需要将其复杂化一点,但幸运的是,如果我们不使用严格的标识=
,JS是相当宽容的
最后,大部分逻辑如下:
return data[item.value] === item.expression
2-评估
这个有点棘手。我实现了一个深度优先的递归函数,它将一次一次地展平初始json对象迭代
每个数组
项都必须先经过评估
,然后才能使用(深度优先和递归)
按照数组的顺序,前3项必须始终包含1个组合符(“或”
或“和”
)和2个值(由计算的先前值,或通过leafValue
传递的对象的结果)<代码>求值
查找哪个是哪个,并应用逻辑运算
在我当前正在评估的数组中,evaluate
将前3项替换为步骤2的结果
重复步骤2。如果没有足够的项目剩余,evaluate
返回数组中剩余的单个值
为了整洁起见,我将它们都包装在一个processData
函数中
函数processData(数据,json){
常量组合符=[“或”,“和”]
功能值(项目){
开关(项目.操作员){
案例“=”:
返回数据[item.value]==item.expression
}
抛出新错误(`unknown comparison operator${item.operator}`)
}
函数求值(json){
const evaluated=json.map(item=>Array.isArray(item)?evaluate(item):item
而(计算长度>=3){
常量块=[已评估[0],已评估[1],已评估[2]]
const combinator=chunk.find(item=>combinants.includes(item))
常量[A,B]=块.filter(项=>!combinators.includes(项))
常量值A=typeof A=='boolean'?A:leafValue(A)
常量值B=typeof B=='boolean'?B:leafValue(B)
const result=combinator=='或'?
(价值A | |价值B):
(价值A和价值B)
评估。拼接(0,3,结果)
}
已评估的返回值[0]
}
返回值(json)
}
常量json={
“真实的”:[
[
“和”,
{
“运算符”:“=”,
“compareType”:“文本”,
“值”:“fname”,
“表达式”:“约翰”
},
{
“运算符”:“=”,
“compareType”:“文本”,
“值”:“lname”,
“表达式”:“Doe”
}
],
“或”,
{
“运算符”:“=”,
“compareType”:“boolean”,
“价值”:“同意”,
“表达”:真实
},
“或”[
“和”,
{
“运算符”:“=”,
“compareType”:“文本”,
“值”:“fname”,
“表达式”:“Jane”
},
{
“运算符”:“=”,
“compareType”:“文本”,
“值”:“lname”,
“表达式”:“Doe”
}
]
]
}
常数数据={
fname:'约翰',
名称:“Doe”,
}
const result=processData(数据,json.truthy)
console.log(result)
从何处获取值
值属性指向表单控件(即输入),因此在解析器中将用户输入的值与表达式进行比较。可以像document.getElementById(condition.value)
那样来访问它,并将其值与表达式中的值进行比较。您希望得到什么结果?为什么有不同的结构,比如前缀和中缀?