二进制树逻辑操作的Json模式验证

时间:2017-02-10 07:37:36

标签: json validation logical-operators boolean-logic jsonschema

这部分用于数据验证,但是如果可以使用json模式验证来完成我的需求,那么我很难解决。我的意见是:

(1 or (1 and 0)) => true

成为json对象:

[1, [1, 0]]

因此验证应该没有错误,但是目前我的架构无法在嵌套数据之间正确处理OR情况。

{
  "allOf": [
    {"$ref": "#/definitions/_items"},
    {
      "allOf": [
        {"$ref": "#/definitions/_or"},
        {
          "items": {
            "$ref": "#/definitions/_and"
          }
        }
      ]
    }
  ],
  "definitions": {
    "_items": {
      "minItems": 1,
      "maxItems": 2,
      "type": "array",
      "items": {
        "anyOf": [
          {"enum": [1,0]},
          {"$ref": "#/definitions/_items"}
        ]
      }
    },
    "_or": {
      "not": {
        "type": "array",
        "items": {
          "not": {
            "anyOf": [
              {"enum": [1]},
              {"$ref": "#/definitions/_items"}
            ]
          }
        }
      }
    },
    "_and": {
      "items": {
        "anyOf": [
          {"enum": [1]},
          {"$ref": "#/definitions/_items"}
        ]
      }
    }
  }
}

根据架构验证下一个数据:

[1,0] is valid, ok
[1,1] is valid, ok
[0,1] is valid, ok
[0,0] not valid, ok
[[1,1],1] valid, ok
[[1,1],0] valid, ok

但:

[[1,0],1] not valid, not ok!
[[0,0],1] not valid, not ok!

因为在OR运算符上都有1,所以如果只是遇到_items定义,左侧应该无关紧要。

所以我的问题是我应该如何更改架构,以便任何OR运算符方都能获得有效输入?

@esp请求更多示例:

我通过逻辑表达式和相应的json数据输入示例:

1 or (1 and 0)) => [1, [1, 0]] => true
1 or (0 and 1)) => [1, [0, 1]] => true
1 or (1 and 1)) => [1, [0, 0]] => true
1 or (0 and 0)) => [1, [0, 0]] => true
1 or (1)) => [1, [1]] => true
1 or (0)) => [1, [0]] => true
1 or 1 => [1, 1 => true
1 or 0 => [1, 0] => true
0 or 1 => [0, 1] => true
0 or 0 => [0, 0] => false

我在左侧也提供了几个嵌套示例,但并非全部,因为组合很快就会疯狂:

(1 and 0) or (1 and 0)) => [[1, 0], [1, 0]] => false
(0 and 0) or (0 and o)) => [[0, 0], [0, 0]] => false
(1 and 1) or (1 and 0)) => [[1, 1], [1, 0]] => true
(1 and 0) or (1 and 1)) => [[1, 0], [1, 1]] => true
(1 and 1) or (1 and 1)) => [[1, 1], [1, 1]] => true

2 个答案:

答案 0 :(得分:1)

使用draft-06关键字"包含" (验证该数组包含至少一个匹配模式的项)和" const" (与" enum"允许的值相同):

{
  "contains": { "$ref": "#/definitions/one" },
  "definitions": {
    "one": {
      "anyOf": [
        { "const": 1 },
        { "$ref": "#/definitions/all" }
      ]
    },
    "all": {
      "type": "array",
      "items": { "$ref": "#/definitions/one" }
    }
  }
}

正如我在评论中写的那样,这个模式只评估你的布尔逻辑,它不验证树是否正确。它还评估所有级别的AND,但第一个。

如果没有draft-06关键字,您可以:

{
  "not": { "items": { "not": { "$ref": "#/definitions/one" } } },
  "definitions": {
    "one": {
      "anyOf": [
        { "enum": [1] },
        { "$ref": "#/definitions/all" }
      ]
    },
    "all": {
      "type": "array",
      "items": { "$ref": "#/definitions/one" }
    }
  }
}

要验证树结构是否有效,您需要另一个简单的模式:

{
  "type": "array",
  "minItems": 1,
  "maxItems": 2,
  "items": {
    "anyOf": [
      { "enum": [0, 1] },
      { "$ref": "#" }
    ]
  }
}

您可以使用" allOf"将这两个模式合并到一起,但是您不会看到具有无效结构的树与评估为false的树之间的差异。

答案 1 :(得分:0)

由于排列相当少,枚举可能的状态使得模式更简单,更易于阅读。

{
  "type": "array",
  "minItems": 1,
  "maxItems": 2,
  "items": {
    "anyOf": [
      { "enum": [0, 1] },
      { "enum": [[0], [1]] },
      { "enum": [[0, 0], [0, 1], [1, 0], [1, 1]] }
    ]
  },
  "allOf": [{ "$ref": "#/definitions/_or" }]
  "definitions": {
    "_or": {
      "not": {
        "items": {
          "not": { "$ref": "#/definitions/_and" }
        }
      }
    },
    "_and": { "enum": [1, [1], [1, 1]] }
  }
}