JSON.net anyOf架构验证问题

时间:2018-03-15 12:02:57

标签: json json.net jsonschema

我使用JSON.Net schema validation package并且遇到了一个非常奇怪的问题。我已在以下anyOf定义中使用anyObject跟踪问题:

{
  "$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"]
  }
}

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

{
  "$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/

上的架构验证程序的在线版本完成的

1 个答案:

答案 0 :(得分:1)

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

要进行调试,我在模式中执行了验证过程,将$refthenelse设置为false ...当我到达computedBody时,我把它改成了以下......

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

验证仍然是积极的,这是不可能的。我通过将该子模式设置为computedBody并看到验证结果为负,证明它达到了false

(不需要包含oneOf子模式的computedBodyif在架构级别上有效就好了。