【问题标题】:Issue with JSON.net anyOf schema validationJSON.net anyOf 模式验证问题
【发布时间】:2018-03-15 12:02:56
【问题描述】:

我正在使用JSON.Net schema validation package,但遇到了一个非常奇怪的问题。我已经在下面的anyObject 定义中找到了使用anyOf 的问题:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/schemas/example/1.0/schema.json",
  "anyOf": [
    {
      "$ref": "#/definitions/anyObject"
    }
  ],
  "definitions": {
    "anyObject": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "anyOf": [
        {
          "if": {
            "properties": {
              "type": {
                "const": "typeA"
              }
            }
          },
          "then": {
            "$ref": "#/definitions/typeA"
          },
          "else": false
        },
        {
          "if": {
            "properties": {
              "type": {
                "const": "typeB"
              }
            }
          },
          "then": {
            "$ref": "#/definitions/typeB"
          },
          "else": false
        }
      ]
    },
    "bodyDefinition": {
      "oneOf": [
        {
          "if": {
            "properties": {
              "$computed": {
                "type": "string"
              }
            },
            "required": [
              "$computed"
            ]
          },
          "then": {
            "$ref": "#/definitions/computedBody"
          },
          "else": {
            "$ref": "#/definitions/wildcardBody"
          }
        },
        {
            "type": "string"
        }
      ]
    },
    "wildcardBody": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/bodyDefinition"
      }
    },
    "firstComputedValue": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "$computed": {
          "const": "first"
        },
        "values": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/bodyDefinition"
          }
        }
      },
      "required": [
        "$computed",
        "values"
      ]
    },
    "computedBody": {
      "oneOf": [
        {
          "if": {
            "properties": {
              "$computed": {
                "const": "first"
              }
            }
          },
          "then": {
            "$ref": "#/definitions/firstComputedValue"
          },
          "else": false
        }
      ]
    },
    "typeA": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "typeA"
        },
        "body": {
          "$ref": "#/definitions/bodyDefinition"
        }
      },
      "required": [
        "type"
      ]
    },
    "typeB": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "typeB"
        },
        "body": {
          "$ref": "#/definitions/bodyDefinition"
        }
      },
      "required": [
        "type"
      ]
    }
  }
}

当我测试这个 json 时:

{
  "type": "typeB",
  "body":{
     "$computed":"first",
     "values":[]
  }
}

应该被标记为无效,因为values 必须至少有一个值。然而它是有效的。下面的 JSON 应该被认为是有效的,上面的模式确实正确地断言:

{
  "type": "typeB",
  "body":{
     "$computed":"first",
     "values":["foo"]
  }
}

如果我从anyObject 定义中删除typeA,则验证会正确执行。以下是正确验证的架构:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "$id": "http://example.com/schemas/example/1.0/schema.json",
  "anyOf": [
    {
      "$ref": "#/definitions/anyObject"
    }
  ],
  "definitions": {
    "anyObject": {
      "type": "object",
      "properties": {
        "type": {
          "type": "string"
        }
      },
      "required": [
        "type"
      ],
      "anyOf": [
        {
          "if": {
            "properties": {
              "type": {
                "const": "typeB"
              }
            }
          },
          "then": {
            "$ref": "#/definitions/typeB"
          },
          "else": false
        }
      ]
    },
    "bodyDefinition": {
      "oneOf": [
        {
          "if": {
            "properties": {
              "$computed": {
                "type": "string"
              }
            },
            "required": [
              "$computed"
            ]
          },
          "then": {
            "$ref": "#/definitions/computedBody"
          },
          "else": {
            "$ref": "#/definitions/wildcardBody"
          }
        },
        {
            "type": "string"
        }
      ]
    },
    "wildcardBody": {
      "type": "object",
      "additionalProperties": {
        "$ref": "#/definitions/bodyDefinition"
      }
    },
    "firstComputedValue": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "$computed": {
          "const": "first"
        },
        "values": {
          "type": "array",
          "minItems": 1,
          "items": {
            "$ref": "#/definitions/bodyDefinition"
          }
        }
      },
      "required": [
        "$computed",
        "values"
      ]
    },
    "computedBody": {
      "oneOf": [
        {
          "if": {
            "properties": {
              "$computed": {
                "const": "first"
              }
            }
          },
          "then": {
            "$ref": "#/definitions/firstComputedValue"
          },
          "else": false
        }
      ]
    },
    "typeA": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "typeA"
        },
        "body": {
          "$ref": "#/definitions/bodyDefinition"
        }
      },
      "required": [
        "type"
      ]
    },
    "typeB": {
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "type": {
          "type": "string",
          "const": "typeB"
        },
        "body": {
          "$ref": "#/definitions/bodyDefinition"
        }
      },
      "required": [
        "type"
      ]
    }
  }
}

谁能看看这个定义是否有问题,或者这是否是 JSON.Net 架构包的问题?

此测试是针对 https://www.jsonschemavalidator.net/ 的架构验证器的在线版本完成的

【问题讨论】:

    标签: json json.net jsonschema


    【解决方案1】:

    我认为这是一个错误。我会和图书馆作者谈谈!

    为了调试,我通过架构跟踪验证过程,将$refthenelse设置为false...当我到达computedBody时,我将其更改为以下...

    "computedBody": {
          "if": {
            "properties": {
              "$computed": {
                "const": "first"
              }
            }
          },
          "then": false,
          "else": false
        }
    

    验证仍然是肯定的,这是不可能的。我通过将该子模式设置为false 并看到验证返回否定结果来证明它达到了computedBody

    (不需要包装computedBody 的子模式的oneOfif 在模式级别有效)。

    【讨论】:

    • 感谢您的调查。是的,这个例子有点做作,因为我试图获得一个最小的例子来复制发布。实际的computedBody 有几个其他选项。感谢您与图书馆作者交谈!
    • 我向他们发了推文并邀请他们加入 JSON Schema slack 来讨论(这个和其他的)。会看看会发生什么。 =] 是否有官方支持论坛,因为它是付费产品?
    • 有,有,我已经给他们发了电子邮件,提供了这个问题的链接,但是你先到了!
    • 我收到了 James Newton-King 的回复。他已经找到了问题,并将在接下来的几天内发布修复程序。
    猜你喜欢
    • 2016-08-06
    • 2019-01-27
    • 2019-04-13
    • 1970-01-01
    • 2018-03-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-04
    相关资源
    最近更新 更多