使用结构化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格式,因为以前的功能依赖于它。在我试图找到一种更简洁的处理方法时,在前面、中间、后面加上“和”、“或”、如何以及在哪里加上“和”、“或”是可选的
  • 不,这不能在SQL或其他服务器端方法中完成
  • 灵感:

  • 发现它具有不同的结构,但支持更深的嵌套和复杂的结构,因此尝试了解如何调整现有解决方案以处理类似的问题

  • 在国际海事组织,您需要两个功能:

    • 一个是用对象、数组等解析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)
    那样来访问它,并将其值与表达式中的值进行比较。您希望得到什么结果?为什么有不同的结构,比如前缀和中缀?